3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-06-08 23:23:25 +00:00

ast, read_verilog: ownership in AST, use C++ styles for parser and lexer

This commit is contained in:
Emil J. Tywoniak 2025-05-21 12:14:50 +02:00
parent 4b8d42d22c
commit 73122921f5
22 changed files with 2496 additions and 2615 deletions

View file

@ -111,7 +111,7 @@ endif
PKG_CONFIG ?= pkg-config PKG_CONFIG ?= pkg-config
SED ?= sed SED ?= sed
BISON ?= bison BISON ?= bison -k
STRIP ?= strip STRIP ?= strip
AWK ?= awk AWK ?= awk

View file

@ -41,7 +41,7 @@
packages.default = yosys; packages.default = yosys;
defaultPackage = yosys; defaultPackage = yosys;
devShell = pkgs.mkShell { devShell = pkgs.mkShell {
buildInputs = with pkgs; [ clang llvmPackages.bintools gcc bison flex libffi tcl readline python3 zlib git gtest abc-verifier verilog boost python3Packages.boost ]; buildInputs = with pkgs; [ clang llvmPackages.bintools gcc bison flex libffi tcl readline python3 zlib git gtest abc-verifier verilog boost python3Packages.boost valgrind ];
}; };
} }
); );

View file

@ -39,8 +39,6 @@ using namespace AST_INTERNAL;
// instantiate global variables (public API) // instantiate global variables (public API)
namespace AST { namespace AST {
std::string current_filename; std::string current_filename;
void (*set_line_num)(int) = NULL;
int (*get_line_num)() = NULL;
unsigned long long astnodes = 0; unsigned long long astnodes = 0;
unsigned long long astnode_count() { return astnodes; } unsigned long long astnode_count() { return astnodes; }
} }
@ -192,16 +190,16 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
if (attributes.count(id) == 0) if (attributes.count(id) == 0)
return false; return false;
AstNode *attr = attributes.at(id); AstNode& attr = *(attributes.at(id));
if (attr->type != AST_CONSTANT) if (attr.type != AST_CONSTANT)
attr->input_error("Attribute `%s' with non-constant value!\n", id.c_str()); attr.input_error("Attribute `%s' with non-constant value!\n", id.c_str());
return attr->integer != 0; return attr.integer != 0;
} }
// 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, AstNode *child1, AstNode *child2, AstNode *child3, AstNode *child4) AstNode::AstNode(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);
@ -239,56 +237,74 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
in_param = false; in_param = false;
if (child1) if (child1)
children.push_back(child1); children.push_back(std::move(child1));
if (child2) if (child2)
children.push_back(child2); children.push_back(std::move(child2));
if (child3) if (child3)
children.push_back(child3); children.push_back(std::move(child3));
if (child4) if (child4)
children.push_back(child4); children.push_back(std::move(child4));
fixup_hierarchy_flags(); fixup_hierarchy_flags();
} }
// create a (deep recursive) copy of a node // create a (deep recursive) copy of a node
AstNode *AstNode::clone() const std::unique_ptr<AstNode> AstNode::clone() const
{ {
AstNode *that = new AstNode; auto that = std::make_unique<AstNode>(this->type);
*that = *this; cloneInto(*that.get());
for (auto &it : that->children)
it = it->clone();
for (auto &it : that->attributes)
it.second = it.second->clone();
that->set_in_lvalue_flag(false);
that->set_in_param_flag(false);
that->fixup_hierarchy_flags(); // fixup to set flags on cloned children
return that; return that;
} }
// create a (deep recursive) copy of a node use 'other' as target root node // create a (deep recursive) copy of a node use 'other' as target root node
void AstNode::cloneInto(AstNode *other) const void AstNode::cloneInto(AstNode &other) const
{ {
AstNode *tmp = clone(); other.type = type;
tmp->in_lvalue_from_above = other->in_lvalue_from_above; other.str = str;
tmp->in_param_from_above = other->in_param_from_above; other.bits = bits;
other->delete_children(); other.is_input = is_input;
*other = *tmp; other.is_output = is_output;
tmp->children.clear(); other.is_reg = is_reg;
tmp->attributes.clear(); other.is_logic = is_logic;
other->fixup_hierarchy_flags(); other.is_signed = is_signed;
delete tmp; other.is_string = is_string;
other.is_wand = is_wand;
other.is_wor = is_wor;
other.range_valid = range_valid;
other.range_swapped = range_swapped;
other.was_checked = was_checked;
other.is_unsized = is_unsized;
other.is_custom_type = is_custom_type;
other.port_id = port_id,
other.range_left = range_left,
other.range_right = range_right;
other.integer = integer;
other.realvalue = realvalue;
other.is_enum = is_enum;
other.dimensions = dimensions;
other.unpacked_dimensions = unpacked_dimensions;
other.id2ast = id2ast;
other.basic_prep = basic_prep;
other.lookahead = lookahead;
other.filename = filename;
other.location = location;
other.in_lvalue = in_lvalue;
other.in_param = in_param;
// Keep in_lvalue_from_above and in_param_from_above untouched
other.delete_children();
for (auto& child : this->children)
other.children.push_back(child->clone());
for (auto& [key, val] : this->attributes)
other.attributes[key] = (val->clone());
// fixup to set flags on cloned children
other.fixup_hierarchy_flags();
} }
// delete all children in this node // delete all children in this node
void AstNode::delete_children() void AstNode::delete_children()
{ {
for (auto &it : children)
delete it;
children.clear(); children.clear();
for (auto &it : attributes)
delete it.second;
attributes.clear(); attributes.clear();
} }
@ -423,18 +439,18 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
{ {
case AST_MODULE: case AST_MODULE:
fprintf(f, "%s" "module %s(", indent.c_str(), id2vl(str).c_str()); fprintf(f, "%s" "module %s(", indent.c_str(), id2vl(str).c_str());
for (auto child : children) for (const auto& child : children)
if (child->type == AST_WIRE && (child->is_input || child->is_output)) { if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
fprintf(f, "%s%s", first ? "" : ", ", id2vl(child->str).c_str()); fprintf(f, "%s%s", first ? "" : ", ", id2vl(child->str).c_str());
first = false; first = false;
} }
fprintf(f, ");\n"); fprintf(f, ");\n");
for (auto child : children) for (const auto& child : children)
if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_DEFPARAM) if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_DEFPARAM)
child->dumpVlog(f, indent + " "); child->dumpVlog(f, indent + " ");
else else
rem_children1.push_back(child); rem_children1.push_back(child.get());
for (auto child : rem_children1) for (auto child : rem_children1)
if (child->type == AST_WIRE || child->type == AST_AUTOWIRE || child->type == AST_MEMORY) if (child->type == AST_WIRE || child->type == AST_AUTOWIRE || child->type == AST_MEMORY)
@ -470,7 +486,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "%s" "reg", (is_input || is_output) ? " " : indent.c_str()); fprintf(f, "%s" "reg", (is_input || is_output) ? " " : indent.c_str());
if (is_signed) if (is_signed)
fprintf(f, " signed"); fprintf(f, " signed");
for (auto child : children) { for (const auto& child : children) {
fprintf(f, " "); fprintf(f, " ");
child->dumpVlog(f, ""); child->dumpVlog(f, "");
} }
@ -486,7 +502,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "%s" "memory", indent.c_str()); fprintf(f, "%s" "memory", indent.c_str());
if (is_signed) if (is_signed)
fprintf(f, " signed"); fprintf(f, " signed");
for (auto child : children) { for (const auto& child : children) {
fprintf(f, " "); fprintf(f, " ");
child->dumpVlog(f, ""); child->dumpVlog(f, "");
if (first) if (first)
@ -500,7 +516,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
if (0) { case AST_MEMINIT: txt = "@meminit@"; } if (0) { case AST_MEMINIT: txt = "@meminit@"; }
if (0) { case AST_MEMWR: txt = "@memwr@"; } if (0) { case AST_MEMWR: txt = "@memwr@"; }
fprintf(f, "%s%s", indent.c_str(), txt.c_str()); fprintf(f, "%s%s", indent.c_str(), txt.c_str());
for (auto child : children) { for (const auto& child : children) {
fprintf(f, first ? "(" : ", "); fprintf(f, first ? "(" : ", ");
child->dumpVlog(f, ""); child->dumpVlog(f, "");
first = false; first = false;
@ -517,7 +533,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
else else
fprintf(f, "[%d:%d]", range_left, range_right); fprintf(f, "[%d:%d]", range_left, range_right);
} else { } else {
for (auto child : children) { for (const auto& child : children) {
fprintf(f, "%c", first ? '[' : ':'); fprintf(f, "%c", first ? '[' : ':');
child->dumpVlog(f, ""); child->dumpVlog(f, "");
first = false; first = false;
@ -527,13 +543,13 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
break; break;
case AST_MULTIRANGE: case AST_MULTIRANGE:
for (auto child : children) for (const auto& child : children)
child->dumpVlog(f, ""); child->dumpVlog(f, "");
break; break;
case AST_ALWAYS: case AST_ALWAYS:
fprintf(f, "%s" "always @", indent.c_str()); fprintf(f, "%s" "always @", indent.c_str());
for (auto child : children) { for (const auto& child : children) {
if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
continue; continue;
fprintf(f, first ? "(" : ", "); fprintf(f, first ? "(" : ", ");
@ -541,7 +557,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
first = false; first = false;
} }
fprintf(f, first ? "*\n" : ")\n"); fprintf(f, first ? "*\n" : ")\n");
for (auto child : children) { for (const auto& child : children) {
if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
child->dumpVlog(f, indent + " "); child->dumpVlog(f, indent + " ");
} }
@ -549,7 +565,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_INITIAL: case AST_INITIAL:
fprintf(f, "%s" "initial\n", indent.c_str()); fprintf(f, "%s" "initial\n", indent.c_str());
for (auto child : children) { for (const auto& child : children) {
if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE) if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
child->dumpVlog(f, indent + " "); child->dumpVlog(f, indent + " ");
} }
@ -562,7 +578,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "posedge "); fprintf(f, "posedge ");
if (type == AST_NEGEDGE) if (type == AST_NEGEDGE)
fprintf(f, "negedge "); fprintf(f, "negedge ");
for (auto child : children) for (const auto& child : children)
child->dumpVlog(f, ""); child->dumpVlog(f, "");
break; break;
@ -574,7 +590,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
else else
fprintf(f, "%s", id2vl(str).c_str()); fprintf(f, "%s", id2vl(str).c_str());
} }
for (auto child : children) for (const auto& child : children)
child->dumpVlog(f, ""); child->dumpVlog(f, "");
break; break;
@ -602,7 +618,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
children[0]->dumpVlog(f, indent); children[0]->dumpVlog(f, indent);
} else { } else {
fprintf(f, "%s" "begin\n", indent.c_str()); fprintf(f, "%s" "begin\n", indent.c_str());
for (auto child : children) for (const auto& child : children)
child->dumpVlog(f, indent + " "); child->dumpVlog(f, indent + " ");
fprintf(f, "%s" "end\n", indent.c_str()); fprintf(f, "%s" "end\n", indent.c_str());
} }
@ -618,7 +634,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
children[0]->dumpVlog(f, ""); children[0]->dumpVlog(f, "");
fprintf(f, ")\n"); fprintf(f, ")\n");
for (size_t i = 1; i < children.size(); i++) { for (size_t i = 1; i < children.size(); i++) {
AstNode *child = children[i]; const auto& child = children[i];
child->dumpVlog(f, indent + " "); child->dumpVlog(f, indent + " ");
} }
fprintf(f, "%s" "endcase\n", indent.c_str()); fprintf(f, "%s" "endcase\n", indent.c_str());
@ -627,7 +643,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_COND: case AST_COND:
case AST_CONDX: case AST_CONDX:
case AST_CONDZ: case AST_CONDZ:
for (auto child : children) { for (const auto& child : children) {
if (child->type == AST_BLOCK) { if (child->type == AST_BLOCK) {
fprintf(f, ":\n"); fprintf(f, ":\n");
child->dumpVlog(f, indent + " "); child->dumpVlog(f, indent + " ");
@ -663,7 +679,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_CONCAT: case AST_CONCAT:
fprintf(f, "{"); fprintf(f, "{");
for (int i = GetSize(children)-1; i >= 0; i--) { for (int i = GetSize(children)-1; i >= 0; i--) {
auto child = children[i]; const auto& child = children[i];
if (!first) if (!first)
fprintf(f, ", "); fprintf(f, ", ");
child->dumpVlog(f, ""); child->dumpVlog(f, "");
@ -818,16 +834,16 @@ bool AstNode::contains(const AstNode *other) const
{ {
if (this == other) if (this == other)
return true; return true;
for (auto child : children) for (const auto& child : children)
if (child->contains(other)) if (child->contains(other))
return true; return true;
return false; return false;
} }
// 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)
AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width) std::unique_ptr<AstNode> AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
{ {
AstNode *node = new AstNode(AST_CONSTANT); auto node = std::make_unique<AstNode>(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++) {
@ -841,9 +857,9 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
} }
// 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)
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized) std::unique_ptr<AstNode> AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
{ {
AstNode *node = new AstNode(AST_CONSTANT); auto node = std::make_unique<AstNode>(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++) {
@ -859,15 +875,15 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
return node; return node;
} }
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed) std::unique_ptr<AstNode> AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
{ {
return mkconst_bits(v, is_signed, false); return mkconst_bits(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)
AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v) std::unique_ptr<AstNode> AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
{ {
AstNode *node = mkconst_str(RTLIL::Const(v).decode_string()); auto node = mkconst_str(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);
@ -875,9 +891,9 @@ 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)
AstNode *AstNode::mkconst_str(const std::string &str) std::unique_ptr<AstNode> AstNode::mkconst_str(const std::string &str)
{ {
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")
@ -902,18 +918,19 @@ AstNode *AstNode::mkconst_str(const std::string &str)
} }
// create a temporary register // create a temporary register
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(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed)
{ {
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(range_left, true), mkconst_int(range_right, true))); 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 = 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(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(1, false));
wire->is_signed = is_signed; wire->is_signed = is_signed;
wire->is_logic = true; wire->is_logic = true;
mod->children.push_back(wire); mod->children.push_back(std::move(wire_owned));
while (wire->simplify(true, 1, -1, false)) { } while (wire->simplify(true, 1, -1, false)) { }
AstNode *ident = new AstNode(AST_IDENTIFIER); auto ident = std::make_unique<AstNode>(AST_IDENTIFIER);
ident->str = wire->str; ident->str = wire->str;
ident->id2ast = wire; ident->id2ast = wire;
@ -967,10 +984,9 @@ RTLIL::Const AstNode::asParaConst() const
{ {
if (type == AST_REALVALUE) if (type == AST_REALVALUE)
{ {
AstNode *strnode = AstNode::mkconst_str(stringf("%f", realvalue)); auto strnode = AstNode::mkconst_str(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;
delete strnode;
return val; return val;
} }
@ -1078,7 +1094,7 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
obj->attributes[ID::src] = ast->loc_string(); obj->attributes[ID::src] = ast->loc_string();
} }
static bool param_has_no_default(const AstNode *param) { static bool param_has_no_default(const std::unique_ptr<AstNode> &param) {
const auto &children = param->children; const auto &children = param->children;
log_assert(param->type == AST_PARAMETER); log_assert(param->type == AST_PARAMETER);
log_assert(children.size() <= 2); log_assert(children.size() <= 2);
@ -1086,7 +1102,7 @@ static bool param_has_no_default(const AstNode *param) {
(children.size() == 1 && children[0]->type == AST_RANGE); (children.size() == 1 && children[0]->type == AST_RANGE);
} }
static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false) static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, std::unique_ptr<AstNode> original_ast = NULL, bool quiet = false)
{ {
log_assert(current_scope.empty()); log_assert(current_scope.empty());
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE); log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
@ -1100,15 +1116,15 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
AstModule *module = new AstModule; AstModule *module = new AstModule;
current_module = module; current_module = module;
module->ast = NULL; module->ast = nullptr;
module->name = ast->str; module->name = ast->str;
set_src_attr(module, ast); set_src_attr(module, ast);
module->set_bool_attribute(ID::cells_not_processed); module->set_bool_attribute(ID::cells_not_processed);
current_ast_mod = ast; current_ast_mod = ast;
AstNode *ast_before_simplify; std::unique_ptr<AstNode> ast_before_simplify;
if (original_ast != NULL) if (original_ast != NULL)
ast_before_simplify = original_ast; ast_before_simplify = std::move(original_ast);
else else
ast_before_simplify = ast->clone(); ast_before_simplify = ast->clone();
@ -1125,7 +1141,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (!defer) if (!defer)
{ {
for (const AstNode *node : ast->children) for (auto& node : ast->children)
if (node->type == AST_PARAMETER && param_has_no_default(node)) if (node->type == AST_PARAMETER && param_has_no_default(node))
node->input_error("Parameter `%s' has no default value and has not been overridden!\n", node->str.c_str()); node->input_error("Parameter `%s' has no default value and has not been overridden!\n", node->str.c_str());
@ -1133,7 +1149,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (!blackbox_module && !flag_noblackbox) { if (!blackbox_module && !flag_noblackbox) {
blackbox_module = true; blackbox_module = true;
for (auto child : ast->children) { for (const auto& child : ast->children) {
if (child->type == AST_WIRE && (child->is_input || child->is_output)) if (child->type == AST_WIRE && (child->is_input || child->is_output))
continue; continue;
if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM) if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
@ -1163,36 +1179,33 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
ast->dumpVlog(NULL, " "); ast->dumpVlog(NULL, " ");
log("--- END OF AST DUMP ---\n"); log("--- END OF AST DUMP ---\n");
} }
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (flag_nowb && ast->attributes.count(ID::whitebox)) { if (flag_nowb && ast->attributes.count(ID::whitebox)) {
delete ast->attributes.at(ID::whitebox);
ast->attributes.erase(ID::whitebox); ast->attributes.erase(ID::whitebox);
} }
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (ast->attributes.count(ID::lib_whitebox)) { if (ast->attributes.count(ID::lib_whitebox)) {
if (!flag_lib || flag_nowb) { if (flag_lib && !flag_nowb) {
delete ast->attributes.at(ID::lib_whitebox); ast->attributes[ID::whitebox] = std::move(
ast->attributes.erase(ID::lib_whitebox); ast->attributes[ID::lib_whitebox]
} else { );
if (ast->attributes.count(ID::whitebox)) {
delete ast->attributes.at(ID::whitebox);
ast->attributes.erase(ID::whitebox);
}
AstNode *n = ast->attributes.at(ID::lib_whitebox);
ast->set_attribute(ID::whitebox, n);
ast->attributes.erase(ID::lib_whitebox);
} }
ast->attributes.erase(ID::lib_whitebox);
} }
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (!blackbox_module && ast->attributes.count(ID::blackbox)) { if (!blackbox_module && ast->attributes.count(ID::blackbox)) {
AstNode *n = ast->attributes.at(ID::blackbox); auto& n = ast->attributes.at(ID::blackbox);
if (n->type != AST_CONSTANT) if (n->type != AST_CONSTANT)
ast->input_error("Got blackbox attribute with non-constant value!\n"); ast->input_error("Got blackbox attribute with non-constant value!\n");
blackbox_module = n->asBool(); blackbox_module = n->asBool();
} }
if (blackbox_module && ast->attributes.count(ID::whitebox)) { if (blackbox_module && ast->attributes.count(ID::whitebox)) {
AstNode *n = ast->attributes.at(ID::whitebox); auto& n = ast->attributes.at(ID::whitebox);
if (n->type != AST_CONSTANT) if (n->type != AST_CONSTANT)
ast->input_error("Got whitebox attribute with non-constant value!\n"); ast->input_error("Got whitebox attribute with non-constant value!\n");
blackbox_module = !n->asBool(); blackbox_module = !n->asBool();
@ -1200,38 +1213,34 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (ast->attributes.count(ID::noblackbox)) { if (ast->attributes.count(ID::noblackbox)) {
if (blackbox_module) { if (blackbox_module) {
AstNode *n = ast->attributes.at(ID::noblackbox); auto& n = ast->attributes.at(ID::noblackbox);
if (n->type != AST_CONSTANT) if (n->type != AST_CONSTANT)
ast->input_error("Got noblackbox attribute with non-constant value!\n"); ast->input_error("Got noblackbox attribute with non-constant value!\n");
blackbox_module = !n->asBool(); blackbox_module = !n->asBool();
} }
delete ast->attributes.at(ID::noblackbox);
ast->attributes.erase(ID::noblackbox); ast->attributes.erase(ID::noblackbox);
} }
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (blackbox_module) if (blackbox_module)
{ {
if (ast->attributes.count(ID::whitebox)) { if (ast->attributes.count(ID::whitebox)) {
delete ast->attributes.at(ID::whitebox);
ast->attributes.erase(ID::whitebox); ast->attributes.erase(ID::whitebox);
} }
if (ast->attributes.count(ID::lib_whitebox)) { if (ast->attributes.count(ID::lib_whitebox)) {
delete ast->attributes.at(ID::lib_whitebox);
ast->attributes.erase(ID::lib_whitebox); ast->attributes.erase(ID::lib_whitebox);
} }
std::vector<AstNode*> new_children; std::vector<std::unique_ptr<AstNode>> new_children;
for (auto child : ast->children) { for (auto& child : ast->children) {
if (child->type == AST_WIRE && (child->is_input || child->is_output)) { if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
new_children.push_back(child); new_children.push_back(std::move(child));
} else if (child->type == AST_PARAMETER) { } else if (child->type == AST_PARAMETER) {
new_children.push_back(child); new_children.push_back(std::move(child));
} else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE && } else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE &&
(child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) { (child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) {
new_children.push_back(child); new_children.push_back(std::move(child));
} else {
delete child;
} }
} }
@ -1245,17 +1254,18 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
ignoreThisSignalsInInitial = RTLIL::SigSpec(); ignoreThisSignalsInInitial = RTLIL::SigSpec();
for (auto &attr : ast->attributes) { for (auto &attr : ast->attributes) {
log_assert((bool)attr.second.get());
if (attr.second->type != AST_CONSTANT) if (attr.second->type != AST_CONSTANT)
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str()); ast->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
module->attributes[attr.first] = attr.second->asAttrConst(); module->attributes[attr.first] = attr.second->asAttrConst();
} }
for (size_t i = 0; i < ast->children.size(); i++) { for (size_t i = 0; i < ast->children.size(); i++) {
AstNode *node = ast->children[i]; const auto& node = ast->children[i];
if (node->type == AST_WIRE || node->type == AST_MEMORY) if (node->type == AST_WIRE || node->type == AST_MEMORY)
node->genRTLIL(); node->genRTLIL();
} }
for (size_t i = 0; i < ast->children.size(); i++) { for (size_t i = 0; i < ast->children.size(); i++) {
AstNode *node = ast->children[i]; const auto& node = ast->children[i];
if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL) if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL)
node->genRTLIL(); node->genRTLIL();
} }
@ -1263,7 +1273,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
ignoreThisSignalsInInitial.sort_and_unify(); ignoreThisSignalsInInitial.sort_and_unify();
for (size_t i = 0; i < ast->children.size(); i++) { for (size_t i = 0; i < ast->children.size(); i++) {
AstNode *node = ast->children[i]; const auto& node = ast->children[i];
if (node->type == AST_INITIAL) if (node->type == AST_INITIAL)
node->genRTLIL(); node->genRTLIL();
} }
@ -1277,14 +1287,14 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
continue; continue;
module->attributes[attr.first] = attr.second->asAttrConst(); module->attributes[attr.first] = attr.second->asAttrConst();
} }
for (const AstNode *node : ast->children) for (const auto& node : ast->children)
if (node->type == AST_PARAMETER) if (node->type == AST_PARAMETER)
current_module->avail_parameters(node->str); current_module->avail_parameters(node->str);
} }
if (ast->type == AST_INTERFACE) if (ast->type == AST_INTERFACE)
module->set_bool_attribute(ID::is_interface); module->set_bool_attribute(ID::is_interface);
module->ast = ast_before_simplify; module->ast = std::move(ast_before_simplify);
module->nolatches = flag_nolatches; module->nolatches = flag_nolatches;
module->nomeminit = flag_nomeminit; module->nomeminit = flag_nomeminit;
module->nomem2reg = flag_nomem2reg; module->nomem2reg = flag_nomem2reg;
@ -1311,8 +1321,8 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
RTLIL::Module * RTLIL::Module *
AST_INTERNAL::process_and_replace_module(RTLIL::Design *design, AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
RTLIL::Module *old_module, RTLIL::Module *old_module,
AstNode *new_ast, AST::AstNode *new_ast,
AstNode *original_ast) std::unique_ptr<AstNode> original_ast)
{ {
// The old module will be deleted. Rename and mark for deletion, using // The old module will be deleted. Rename and mark for deletion, using
// a static counter to make sure we get a unique name. // a static counter to make sure we get a unique name.
@ -1335,7 +1345,7 @@ AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
} }
// Generate RTLIL from AST for the new module and add to the design: // Generate RTLIL from AST for the new module and add to the design:
RTLIL::Module* new_module = process_module(design, new_ast, false, original_ast); RTLIL::Module* new_module = process_module(design, new_ast, false, std::move(original_ast));
if (is_top) if (is_top)
new_module->set_bool_attribute(ID::top); new_module->set_bool_attribute(ID::top);
@ -1347,17 +1357,17 @@ AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
static void rename_in_package_stmts(AstNode *pkg) static void rename_in_package_stmts(AstNode *pkg)
{ {
std::unordered_set<std::string> idents; std::unordered_set<std::string> idents;
for (AstNode *item : pkg->children) for (auto& item : pkg->children)
idents.insert(item->str); idents.insert(item->str);
std::function<void(AstNode*)> rename = std::function<void(std::unique_ptr<AstNode>&)> rename =
[&rename, &idents, pkg](AstNode *node) { [&rename, &idents, pkg](std::unique_ptr<AstNode>& node) {
for (AstNode *child : node->children) { for (auto& child : node->children) {
if (idents.count(child->str)) if (idents.count(child->str))
child->str = pkg->str + "::" + child->str.substr(1); child->str = pkg->str + "::" + child->str.substr(1);
rename(child); rename(child);
} }
}; };
for (AstNode *item : pkg->children) for (auto& item : pkg->children)
if (item->type == AST_FUNCTION || item->type == AST_TASK) if (item->type == AST_FUNCTION || item->type == AST_TASK)
rename(item); rename(item);
} }
@ -1390,17 +1400,17 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
ast->fixup_hierarchy_flags(true); ast->fixup_hierarchy_flags(true);
log_assert(current_ast->type == AST_DESIGN); log_assert(current_ast->type == AST_DESIGN);
for (AstNode *child : current_ast->children) for (const auto& child : current_ast->children)
{ {
if (child->type == AST_MODULE || child->type == AST_INTERFACE) if (child->type == AST_MODULE || child->type == AST_INTERFACE)
{ {
for (auto n : design->verilog_globals) for (auto& n : design->verilog_globals)
child->children.push_back(n->clone()); child->children.push_back(n->clone());
// append nodes from previous packages using package-qualified names // append nodes from previous packages using package-qualified names
for (auto &n : design->verilog_packages) { for (auto& n : design->verilog_packages) {
for (auto &o : n->children) { for (auto &o : n->children) {
AstNode *cloned_node = o->clone(); auto cloned_node = o->clone();
// log("cloned node %s\n", type2str(cloned_node->type).c_str()); // log("cloned node %s\n", type2str(cloned_node->type).c_str());
if (cloned_node->type == AST_ENUM) { if (cloned_node->type == AST_ENUM) {
for (auto &e : cloned_node->children) { for (auto &e : cloned_node->children) {
@ -1410,7 +1420,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
} else { } else {
cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1); cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1);
} }
child->children.push_back(cloned_node); child->children.push_back(std::move(cloned_node));
} }
} }
@ -1419,7 +1429,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
bool defer_local = defer; bool defer_local = defer;
if (!defer_local) if (!defer_local)
for (const AstNode *node : child->children) for (const auto& node : child->children)
if (node->type == AST_PARAMETER && param_has_no_default(node)) if (node->type == AST_PARAMETER && param_has_no_default(node))
{ {
log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str.c_str()); log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str.c_str());
@ -1447,13 +1457,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
} }
} }
process_module(design, child, defer_local); process_module(design, child.get(), defer_local);
current_ast_mod = nullptr; current_ast_mod = nullptr;
} }
else if (child->type == AST_PACKAGE) { else if (child->type == AST_PACKAGE) {
// process enum/other declarations // process enum/other declarations
child->simplify(true, 1, -1, false); child->simplify(true, 1, -1, false);
rename_in_package_stmts(child); rename_in_package_stmts(child.get());
design->verilog_packages.push_back(child->clone()); design->verilog_packages.push_back(child->clone());
current_scope.clear(); current_scope.clear();
} }
@ -1472,14 +1482,6 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
} }
} }
// AstModule destructor
AstModule::~AstModule()
{
if (ast != NULL)
delete ast;
}
// An interface port with modport is specified like this: // An interface port with modport is specified like this:
// <interface_name>.<modport_name> // <interface_name>.<modport_name>
// This function splits the interface_name from the modport_name, and fails if it is not a valid combination // This function splits the interface_name from the modport_name, and fails if it is not a valid combination
@ -1516,7 +1518,7 @@ AstNode * AST::find_modport(AstNode *intf, std::string name)
for (auto &ch : intf->children) for (auto &ch : intf->children)
if (ch->type == AST_MODPORT) if (ch->type == AST_MODPORT)
if (ch->str == name) // Modport found if (ch->str == name) // Modport found
return ch; return ch.get();
return NULL; return NULL;
} }
@ -1524,7 +1526,7 @@ AstNode * AST::find_modport(AstNode *intf, std::string name)
void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport) void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport)
{ {
for (auto w : intfmodule->wires()){ for (auto w : intfmodule->wires()){
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true))); auto wire = std::make_unique<AstNode>(AST_WIRE, std::make_unique<AstNode>(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true)));
std::string origname = log_id(w->name); std::string origname = log_id(w->name);
std::string newname = intfname + "." + origname; std::string newname = intfname + "." + origname;
wire->str = newname; wire->str = newname;
@ -1543,16 +1545,13 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule
} }
} }
if (found_in_modport) { if (found_in_modport) {
module_ast->children.push_back(wire); module_ast->children.push_back(std::move(wire));
}
else { // If not found in modport, do not create port
delete wire;
} }
} }
else { // If no modport, set inout else { // If no modport, set inout
wire->is_input = true; wire->is_input = true;
wire->is_output = true; wire->is_output = true;
module_ast->children.push_back(wire); module_ast->children.push_back(std::move(wire));
} }
} }
} }
@ -1570,7 +1569,7 @@ bool AstModule::reprocess_if_necessary(RTLIL::Design *design)
log("Reprocessing module %s because instantiated module %s has become available.\n", log("Reprocessing module %s because instantiated module %s has become available.\n",
log_id(name), log_id(modname)); log_id(name), log_id(modname));
loadconfig(); loadconfig();
process_and_replace_module(design, this, ast, NULL); process_and_replace_module(design, this, ast.get(), NULL);
return true; return true;
} }
} }
@ -1583,32 +1582,32 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
{ {
loadconfig(); loadconfig();
AstNode *new_ast = ast->clone(); auto new_ast = ast->clone();
for (auto &intf : local_interfaces) { for (auto &intf : local_interfaces) {
std::string intfname = intf.first.str(); std::string intfname = intf.first.str();
RTLIL::Module *intfmodule = intf.second; RTLIL::Module *intfmodule = intf.second;
for (auto w : intfmodule->wires()){ for (auto w : intfmodule->wires()){
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true))); auto wire = std::make_unique<AstNode>(AST_WIRE, std::make_unique<AstNode>(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true)));
std::string newname = log_id(w->name); std::string newname = log_id(w->name);
newname = intfname + "." + newname; newname = intfname + "." + newname;
wire->str = newname; wire->str = newname;
new_ast->children.push_back(wire); new_ast->children.push_back(std::move(wire));
} }
} }
AstNode *ast_before_replacing_interface_ports = new_ast->clone(); auto ast_before_replacing_interface_ports = new_ast->clone();
// Explode all interface ports. Note this will only have an effect on 'top // Explode all interface ports. Note this will only have an effect on 'top
// level' modules. Other sub-modules will have their interface ports // level' modules. Other sub-modules will have their interface ports
// exploded via the derive(..) function // exploded via the derive(..) function
for (size_t i =0; i<new_ast->children.size(); i++) for (size_t i =0; i<new_ast->children.size(); i++)
{ {
AstNode *ch2 = new_ast->children[i]; const auto& ch2 = new_ast->children[i];
if (ch2->type == AST_INTERFACEPORT) { // Is an interface port if (ch2->type == AST_INTERFACEPORT) { // Is an interface port
std::string name_port = ch2->str; // Name of the interface port std::string name_port = ch2->str; // Name of the interface port
if (ch2->children.size() > 0) { if (ch2->children.size() > 0) {
for(size_t j=0; j<ch2->children.size();j++) { for(size_t j=0; j<ch2->children.size();j++) {
AstNode *ch = ch2->children[j]; const auto& ch = ch2->children[j];
if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface
std::pair<std::string,std::string> res = split_modport_from_type(ch->str); std::pair<std::string,std::string> res = split_modport_from_type(ch->str);
std::string interface_type = res.first; std::string interface_type = res.first;
@ -1616,11 +1615,11 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
if (design->module(interface_type) != nullptr) { if (design->module(interface_type) != nullptr) {
// Add a cell to the module corresponding to the interface port such that // Add a cell to the module corresponding to the interface port such that
// it can further propagated down if needed: // it can further propagated down if needed:
AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE); auto celltype_for_intf = std::make_unique<AstNode>(AST_CELLTYPE);
celltype_for_intf->str = interface_type; celltype_for_intf->str = interface_type;
AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf); auto cell_for_intf = std::make_unique<AstNode>(AST_CELL, std::move(celltype_for_intf));
cell_for_intf->str = name_port + "_inst_from_top_dummy"; cell_for_intf->str = name_port + "_inst_from_top_dummy";
new_ast->children.push_back(cell_for_intf); new_ast->children.push_back(std::move(cell_for_intf));
// Get all members of this non-overridden dummy interface instance: // Get all members of this non-overridden dummy interface instance:
RTLIL::Module *intfmodule = design->module(interface_type); // All interfaces should at this point in time (assuming RTLIL::Module *intfmodule = design->module(interface_type); // All interfaces should at this point in time (assuming
@ -1628,9 +1627,9 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
// present in design->modules_ // present in design->modules_
AstModule *ast_module_of_interface = (AstModule*)intfmodule; AstModule *ast_module_of_interface = (AstModule*)intfmodule;
std::string interface_modport_compare_str = "\\" + interface_modport; std::string interface_modport_compare_str = "\\" + interface_modport;
AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport AstNode *modport = find_modport(ast_module_of_interface->ast.get(), interface_modport_compare_str); // modport == NULL if no modport
// Iterate over all wires in the interface and add them to the module: // Iterate over all wires in the interface and add them to the module:
explode_interface_port(new_ast, intfmodule, name_port, modport); explode_interface_port(new_ast.get(), intfmodule, name_port, modport);
} }
break; break;
} }
@ -1642,9 +1641,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
// Generate RTLIL from AST for the new module and add to the design, // Generate RTLIL from AST for the new module and add to the design,
// renaming this module to move it out of the way. // renaming this module to move it out of the way.
RTLIL::Module* new_module = RTLIL::Module* new_module =
process_and_replace_module(design, this, new_ast, ast_before_replacing_interface_ports); process_and_replace_module(design, this, new_ast.get(), std::move(ast_before_replacing_interface_ports));
delete new_ast;
// Set the attribute "interfaces_replaced_in_module" so that it does not happen again. // Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
new_module->set_bool_attribute(ID::interfaces_replaced_in_module); new_module->set_bool_attribute(ID::interfaces_replaced_in_module);
@ -1654,7 +1651,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
// This method is used to explode the interface when the interface is a port of the module (not instantiated inside) // This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool /*mayfail*/) RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool /*mayfail*/)
{ {
AstNode *new_ast = NULL; std::unique_ptr<AstNode> new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast); std::string modname = derive_common(design, parameters, &new_ast);
// Since interfaces themselves may be instantiated with different parameters, // Since interfaces themselves may be instantiated with different parameters,
@ -1690,14 +1687,14 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
if (modports.count(intfname) > 0) { if (modports.count(intfname) > 0) {
std::string interface_modport = modports.at(intfname).str(); std::string interface_modport = modports.at(intfname).str();
AstModule *ast_module_of_interface = (AstModule*)intfmodule; AstModule *ast_module_of_interface = (AstModule*)intfmodule;
AstNode *ast_node_of_interface = ast_module_of_interface->ast; AstNode *ast_node_of_interface = ast_module_of_interface->ast.get();
modport = find_modport(ast_node_of_interface, interface_modport); modport = find_modport(ast_node_of_interface, interface_modport);
} }
// Iterate over all wires in the interface and add them to the module: // Iterate over all wires in the interface and add them to the module:
explode_interface_port(new_ast, intfmodule, intfname, modport); explode_interface_port(new_ast.get(), intfmodule, intfname, modport);
} }
process_module(design, new_ast, false); process_module(design, new_ast.get(), false);
design->module(modname)->check(); design->module(modname)->check();
RTLIL::Module* mod = design->module(modname); RTLIL::Module* mod = design->module(modname);
@ -1734,7 +1731,6 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
} }
delete new_ast;
return modname; return modname;
} }
@ -1743,18 +1739,17 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
{ {
bool quiet = lib || attributes.count(ID::blackbox) || attributes.count(ID::whitebox); bool quiet = lib || attributes.count(ID::blackbox) || attributes.count(ID::whitebox);
AstNode *new_ast = NULL; std::unique_ptr<AstNode> new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast, quiet); std::string modname = derive_common(design, parameters, &new_ast, quiet);
if (!design->has(modname) && new_ast) { if (!design->has(modname) && new_ast) {
new_ast->str = modname; new_ast->str = modname;
process_module(design, new_ast, false, NULL, quiet); process_module(design, new_ast.get(), false, NULL, quiet);
design->module(modname)->check(); design->module(modname)->check();
} else if (!quiet) { } else if (!quiet) {
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str()); log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
} }
delete new_ast;
return modname; return modname;
} }
@ -1784,7 +1779,7 @@ std::string AST::derived_module_name(std::string stripped_name, const std::vecto
} }
// create a new parametric module (when needed) and return the name of the generated module // create a new parametric module (when needed) and return the name of the generated module
std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet) std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, std::unique_ptr<AstNode>* new_ast_out, bool quiet)
{ {
std::string stripped_name = name.str(); std::string stripped_name = name.str();
(*new_ast_out) = nullptr; (*new_ast_out) = nullptr;
@ -1794,7 +1789,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
int para_counter = 0; int para_counter = 0;
std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> named_parameters; std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> named_parameters;
for (const auto child : ast->children) { for (const auto& child : ast->children) {
if (child->type != AST_PARAMETER) if (child->type != AST_PARAMETER)
continue; continue;
para_counter++; para_counter++;
@ -1828,12 +1823,12 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
pool<IdString> rewritten; pool<IdString> rewritten;
rewritten.reserve(GetSize(parameters)); rewritten.reserve(GetSize(parameters));
AstNode *new_ast = ast->clone(); auto new_ast = ast->clone();
if (!new_ast->attributes.count(ID::hdlname)) if (!new_ast->attributes.count(ID::hdlname))
new_ast->set_attribute(ID::hdlname, AstNode::mkconst_str(stripped_name.substr(1))); new_ast->set_attribute(ID::hdlname, AstNode::mkconst_str(stripped_name.substr(1)));
para_counter = 0; para_counter = 0;
for (auto child : new_ast->children) { for (auto& child : new_ast->children) {
if (child->type != AST_PARAMETER) if (child->type != AST_PARAMETER)
continue; continue;
para_counter++; para_counter++;
@ -1853,9 +1848,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
rewrite_parameter: rewrite_parameter:
if (param_has_no_default(child)) if (param_has_no_default(child))
child->children.insert(child->children.begin(), nullptr); child->children.insert(child->children.begin(), nullptr);
delete child->children.at(0);
if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) { if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) {
child->children[0] = new AstNode(AST_REALVALUE); child->children[0] = std::make_unique<AstNode>(AST_REALVALUE);
child->children[0]->realvalue = std::stod(it->second.decode_string()); child->children[0]->realvalue = std::stod(it->second.decode_string());
} else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0) } else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0)
child->children[0] = AstNode::mkconst_str(it->second.decode_string()); child->children[0] = AstNode::mkconst_str(it->second.decode_string());
@ -1868,17 +1862,17 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
for (const auto &param : parameters) { for (const auto &param : parameters) {
if (rewritten.count(param.first)) if (rewritten.count(param.first))
continue; continue;
AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER)); auto defparam = std::make_unique<AstNode>(AST_DEFPARAM, std::make_unique<AstNode>(AST_IDENTIFIER));
defparam->children[0]->str = param.first.str(); defparam->children[0]->str = param.first.str();
if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0) if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0)
defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string())); defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string()));
else else
defparam->children.push_back(AstNode::mkconst_bits(param.second.to_bits(), (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0)); defparam->children.push_back(AstNode::mkconst_bits(param.second.to_bits(), (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0));
new_ast->children.push_back(defparam); new_ast->children.push_back(std::move(defparam));
} }
new_ast->fixup_hierarchy_flags(true); new_ast->fixup_hierarchy_flags(true);
(*new_ast_out) = new_ast; new_ast_out->reset(new_ast.release());
return modname; return modname;
} }

View file

@ -183,10 +183,10 @@ namespace AST
AstNodeType type; AstNodeType type;
// the list of child nodes for this node // the list of child nodes for this node
std::vector<AstNode*> children; std::vector<std::unique_ptr<AstNode>> children;
// the list of attributes assigned to this node // the list of attributes assigned to this node
std::map<RTLIL::IdString, AstNode*> attributes; std::map<RTLIL::IdString, std::unique_ptr<AstNode>> attributes;
bool get_bool_attribute(RTLIL::IdString id); bool get_bool_attribute(RTLIL::IdString id);
// node content - most of it is unused in most node types // node content - most of it is unused in most node types
@ -212,7 +212,7 @@ namespace AST
int unpacked_dimensions; int unpacked_dimensions;
// this is set by simplify and used during RTLIL generation // this is set by simplify and used during RTLIL generation
AstNode *id2ast; AstNode* id2ast;
// this is used by simplify to detect if basic analysis has been performed already on the node // this is used by simplify to detect if basic analysis has been performed already on the node
bool basic_prep; bool basic_prep;
@ -234,9 +234,9 @@ 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, AstNode *child1 = nullptr, AstNode *child2 = nullptr, AstNode *child3 = nullptr, AstNode *child4 = nullptr); 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 *clone() const; std::unique_ptr<AstNode> clone() const;
void cloneInto(AstNode *other) const; void cloneInto(AstNode &other) const;
void delete_children(); void delete_children();
~AstNode(); ~AstNode();
@ -264,15 +264,16 @@ namespace AST
// simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc. // simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc.
// it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL() // it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL()
bool simplify(bool const_fold, int stage, int width_hint, bool sign_hint); bool simplify(bool const_fold, int stage, int width_hint, bool sign_hint);
void null_check();
void replace_result_wire_name_in_function(const std::string &from, const std::string &to); void replace_result_wire_name_in_function(const std::string &from, const std::string &to);
AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init); std::unique_ptr<AstNode> readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
void expand_genblock(const std::string &prefix); void expand_genblock(const std::string &prefix);
void label_genblks(std::set<std::string>& existing, int &counter); void label_genblks(std::set<std::string>& existing, int &counter);
void mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places, void mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places,
dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags); dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags);
bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block); bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode* async_block);
bool mem2reg_check(pool<AstNode*> &mem2reg_set); bool mem2reg_check(pool<AstNode*> &mem2reg_set);
void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes); void mem2reg_remove(pool<AstNode*> &mem2reg_set);
void meminfo(int &mem_width, int &mem_size, int &addr_bits); void meminfo(int &mem_width, int &mem_size, int &addr_bits);
bool detect_latch(const std::string &var); bool detect_latch(const std::string &var);
const RTLIL::Module* lookup_cell_module(); const RTLIL::Module* lookup_cell_module();
@ -288,7 +289,7 @@ namespace AST
}; };
bool has_const_only_constructs(); bool has_const_only_constructs();
bool replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall, bool must_succeed); bool replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall, bool must_succeed);
AstNode *eval_const_function(AstNode *fcall, bool must_succeed); std::unique_ptr<AstNode> eval_const_function(AstNode *fcall, bool must_succeed);
bool is_simple_const_expr(); bool is_simple_const_expr();
// helper for parsing format strings // helper for parsing format strings
@ -305,29 +306,30 @@ namespace AST
std::vector<RTLIL::Binding *> genBindings() const; std::vector<RTLIL::Binding *> genBindings() const;
// used by genRTLIL() for detecting expression width and sign // used by genRTLIL() for detecting expression width and sign
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = NULL); void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = nullptr);
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = NULL); void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = nullptr);
// create RTLIL code for this AST node // create RTLIL code for this AST node
// for expressions the resulting signal vector is returned // for expressions the resulting signal vector is returned
// all generated cell instances, etc. are written to the RTLIL::Module pointed to by AST_INTERNAL::current_module // all generated cell instances, etc. are written to the RTLIL::Module pointed to by AST_INTERNAL::current_module
RTLIL::SigSpec genRTLIL(int width_hint = -1, bool sign_hint = false); RTLIL::SigSpec genRTLIL(int width_hint = -1, bool sign_hint = false);
RTLIL::SigSpec genWidthRTLIL(int width, bool sgn, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr = NULL); RTLIL::SigSpec genWidthRTLIL(int width, bool sgn, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr = nullptr);
// compare AST nodes // compare AST nodes
bool operator==(const AstNode &other) const; bool operator==(const AstNode &other) const;
bool operator!=(const AstNode &other) const; bool operator!=(const AstNode &other) const;
bool contains(const AstNode *other) const; bool contains(const AstNode *other) const;
AstNode operator=(AstNode) = delete;
// helper functions for creating AST nodes for constants // helper functions for creating AST nodes for constants
static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32); static std::unique_ptr<AstNode> mkconst_int(uint32_t v, bool is_signed, int width = 32);
static AstNode *mkconst_bits(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, bool is_unsized);
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed); static std::unique_ptr<AstNode> mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
static AstNode *mkconst_str(const std::vector<RTLIL::State> &v); static std::unique_ptr<AstNode> mkconst_str(const std::vector<RTLIL::State> &v);
static AstNode *mkconst_str(const std::string &str); static std::unique_ptr<AstNode> mkconst_str(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
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(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);
@ -356,12 +358,12 @@ namespace AST
// helper to clone the node with some of its subexpressions replaced with zero (this is used // helper to clone the node with some of its subexpressions replaced with zero (this is used
// to evaluate widths of dynamic ranges) // to evaluate widths of dynamic ranges)
AstNode *clone_at_zero(); std::unique_ptr<AstNode> clone_at_zero();
void set_attribute(RTLIL::IdString key, AstNode *node) void set_attribute(RTLIL::IdString key, std::unique_ptr<AstNode> node)
{ {
attributes[key] = node;
node->set_in_param_flag(true); node->set_in_param_flag(true);
attributes[key] = std::move(node);
} }
// helper to set in_lvalue/in_param flags from the hierarchy context (the actual flag // helper to set in_lvalue/in_param flags from the hierarchy context (the actual flag
@ -377,7 +379,7 @@ namespace AST
void fixup_hierarchy_flags(bool force_descend = false); void fixup_hierarchy_flags(bool force_descend = false);
// helpers for indexing // helpers for indexing
AstNode *make_index_range(AstNode *node, bool unpacked_range = false); std::unique_ptr<AstNode> make_index_range(AstNode *node, bool unpacked_range = false);
AstNode *get_struct_member() const; AstNode *get_struct_member() const;
// helper to print errors from simplify/genrtlil code // helper to print errors from simplify/genrtlil code
@ -391,12 +393,11 @@ namespace AST
// parametric modules are supported directly by the AST library // parametric modules are supported directly by the AST library
// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions // therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
struct AstModule : RTLIL::Module { struct AstModule : RTLIL::Module {
AstNode *ast; std::unique_ptr<AstNode> ast;
bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire; bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire;
~AstModule() override;
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail) override; RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail) override;
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail) override; RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail) override;
std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet = false); std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, std::unique_ptr<AstNode>* new_ast_out, bool quiet = false);
void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override; void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override;
bool reprocess_if_necessary(RTLIL::Design *design) override; bool reprocess_if_necessary(RTLIL::Design *design) override;
RTLIL::Module *clone() const override; RTLIL::Module *clone() const override;
@ -407,8 +408,6 @@ namespace AST
// the AstNode constructor then uses current_filename and get_line_num() // the AstNode constructor then uses current_filename and get_line_num()
// 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;
extern void (*set_line_num)(int);
extern int (*get_line_num)();
// for stats // for stats
unsigned long long astnode_count(); unsigned long long astnode_count();
@ -418,7 +417,7 @@ namespace AST
void use_internal_line_num(); void use_internal_line_num();
// call a DPI function // call a DPI function
AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args); 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);
// 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);
@ -464,7 +463,7 @@ namespace AST_INTERNAL
process_and_replace_module(RTLIL::Design *design, process_and_replace_module(RTLIL::Design *design,
RTLIL::Module *old_module, RTLIL::Module *old_module,
AST::AstNode *new_ast, AST::AstNode *new_ast,
AST::AstNode *original_ast = nullptr); std::unique_ptr<AST::AstNode> original_ast = nullptr);
} }
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END

View file

@ -64,9 +64,9 @@ 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());
} }
AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args) 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)
{ {
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; };
std::vector<value> value_store(args.size() + 1); std::vector<value> value_store(args.size() + 1);
std::vector<ffi_type *> types(args.size() + 1); std::vector<ffi_type *> types(args.size() + 1);
@ -125,11 +125,11 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname,
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 = new AstNode(AST_REALVALUE); newNode = std::make_unique<AstNode>(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 = new AstNode(AST_REALVALUE); newNode = std::make_unique<AstNode>(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") {

View file

@ -85,7 +85,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
set_src_attr(wire, that); set_src_attr(wire, that);
wire->is_signed = that->is_signed; wire->is_signed = that->is_signed;
if (that != NULL) if (that != nullptr)
for (auto &attr : that->attributes) { for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT) if (attr.second->type != AST_CONSTANT)
that->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str()); that->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
@ -195,22 +195,22 @@ struct AST_INTERNAL::LookaheadRewriter
if (node->lookahead) { if (node->lookahead) {
log_assert(node->type == AST_IDENTIFIER); log_assert(node->type == AST_IDENTIFIER);
if (!lookaheadids.count(node->str)) { if (!lookaheadids.count(node->str)) {
AstNode *wire = new AstNode(AST_WIRE); auto wire = std::make_unique<AstNode>(AST_WIRE);
for (auto c : node->id2ast->children) for (auto& c : node->id2ast->children)
wire->children.push_back(c->clone()); wire->children.push_back(c->clone());
wire->fixup_hierarchy_flags(); wire->fixup_hierarchy_flags();
wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++); wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++);
wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false)); wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
wire->is_logic = true; wire->is_logic = true;
while (wire->simplify(true, 1, -1, false)) { } while (wire->simplify(true, 1, -1, false)) { }
current_ast_mod->children.push_back(wire); lookaheadids[node->str] = make_pair(node->id2ast, wire.get());
lookaheadids[node->str] = make_pair(node->id2ast, wire);
wire->genRTLIL(); wire->genRTLIL();
current_ast_mod->children.push_back(std::move(wire));
} }
} }
for (auto child : node->children) for (auto& child : node->children)
collect_lookaheadids(child); collect_lookaheadids(child.get());
} }
bool has_lookaheadids(AstNode *node) bool has_lookaheadids(AstNode *node)
@ -218,8 +218,8 @@ struct AST_INTERNAL::LookaheadRewriter
if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0) if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0)
return true; return true;
for (auto child : node->children) for (auto& child : node->children)
if (has_lookaheadids(child)) if (has_lookaheadids(child.get()))
return true; return true;
return false; return false;
@ -230,8 +230,8 @@ struct AST_INTERNAL::LookaheadRewriter
if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0) if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0)
return true; return true;
for (auto child : node->children) for (auto& child : node->children)
if (has_nonlookaheadids(child)) if (has_nonlookaheadids(child.get()))
return true; return true;
return false; return false;
@ -241,16 +241,16 @@ struct AST_INTERNAL::LookaheadRewriter
{ {
if (node->type == AST_ASSIGN_LE) if (node->type == AST_ASSIGN_LE)
{ {
if (has_lookaheadids(node->children[0])) if (has_lookaheadids(node->children[0].get()))
{ {
if (has_nonlookaheadids(node->children[0])) if (has_nonlookaheadids(node->children[0].get()))
log_error("incompatible mix of lookahead and non-lookahead IDs in LHS expression.\n"); log_error("incompatible mix of lookahead and non-lookahead IDs in LHS expression.\n");
rewrite_lookaheadids(node->children[0], true); rewrite_lookaheadids(node->children[0].get(), true);
node->type = AST_ASSIGN_EQ; node->type = AST_ASSIGN_EQ;
} }
rewrite_lookaheadids(node->children[1], lhs); rewrite_lookaheadids(node->children[1].get(), lhs);
return; return;
} }
@ -261,21 +261,21 @@ struct AST_INTERNAL::LookaheadRewriter
lhs = false; lhs = false;
} }
for (auto child : node->children) for (auto& child : node->children)
rewrite_lookaheadids(child, lhs); rewrite_lookaheadids(child.get(), lhs);
} }
LookaheadRewriter(AstNode *top) LookaheadRewriter(AstNode *top)
{ {
// top->dumpAst(NULL, "REWRITE-BEFORE> "); // top->dumpAst(nullptr, "REWRITE-BEFORE> ");
// top->dumpVlog(NULL, "REWRITE-BEFORE> "); // top->dumpVlog(nullptr, "REWRITE-BEFORE> ");
AstNode *block = nullptr; AstNode *block = nullptr;
for (auto c : top->children) for (auto& c : top->children)
if (c->type == AST_BLOCK) { if (c->type == AST_BLOCK) {
log_assert(block == nullptr); log_assert(block == nullptr);
block = c; block = c.get();
} }
log_assert(block != nullptr); log_assert(block != nullptr);
@ -284,25 +284,25 @@ struct AST_INTERNAL::LookaheadRewriter
for (auto it : lookaheadids) for (auto it : lookaheadids)
{ {
AstNode *ref_orig = new AstNode(AST_IDENTIFIER); auto ref_orig = std::make_unique<AstNode>(AST_IDENTIFIER);
ref_orig->str = it.second.first->str; ref_orig->str = it.second.first->str;
ref_orig->id2ast = it.second.first; ref_orig->id2ast = it.second.first;
ref_orig->was_checked = true; ref_orig->was_checked = true;
AstNode *ref_temp = new AstNode(AST_IDENTIFIER); auto ref_temp = std::make_unique<AstNode>(AST_IDENTIFIER);
ref_temp->str = it.second.second->str; ref_temp->str = it.second.second->str;
ref_temp->id2ast = it.second.second; ref_temp->id2ast = it.second.second;
ref_temp->was_checked = true; ref_temp->was_checked = true;
AstNode *init_assign = new AstNode(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone()); auto init_assign = std::make_unique<AstNode>(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone());
AstNode *final_assign = new AstNode(AST_ASSIGN_LE, ref_orig, ref_temp); auto final_assign = std::make_unique<AstNode>(AST_ASSIGN_LE, std::move(ref_orig), std::move(ref_temp));
block->children.insert(block->children.begin(), init_assign); block->children.insert(block->children.begin(), std::move(init_assign));
block->children.push_back(final_assign); block->children.push_back(std::move(final_assign));
} }
// top->dumpAst(NULL, "REWRITE-AFTER> "); // top->dumpAst(nullptr, "REWRITE-AFTER> ");
// top->dumpVlog(NULL, "REWRITE-AFTER> "); // top->dumpVlog(nullptr, "REWRITE-AFTER> ");
} }
}; };
@ -310,7 +310,7 @@ struct AST_INTERNAL::LookaheadRewriter
struct AST_INTERNAL::ProcessGenerator struct AST_INTERNAL::ProcessGenerator
{ {
// input and output structures // input and output structures
AstNode *always; std::unique_ptr<AstNode> always;
RTLIL::SigSpec initSyncSignals; RTLIL::SigSpec initSyncSignals;
RTLIL::Process *proc; RTLIL::Process *proc;
RTLIL::SigSpec outputSignals; RTLIL::SigSpec outputSignals;
@ -341,14 +341,14 @@ struct AST_INTERNAL::ProcessGenerator
// The most recently assigned $print or $check cell \PRIORITY. // The most recently assigned $print or $check cell \PRIORITY.
int last_effect_priority; int last_effect_priority;
ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg), last_effect_priority(0) ProcessGenerator(std::unique_ptr<AstNode> a, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(std::move(a)), initSyncSignals(initSyncSignalsArg), last_effect_priority(0)
{ {
// rewrite lookahead references // rewrite lookahead references
LookaheadRewriter la_rewriter(always); 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->filename).c_str(), always->location.first_line, autoidx++));
set_src_attr(proc, always); 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)
always->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str()); always->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
@ -358,13 +358,13 @@ struct AST_INTERNAL::ProcessGenerator
// create initial temporary signal for all output registers // create initial temporary signal for all output registers
RTLIL::SigSpec subst_lvalue_from, subst_lvalue_to; RTLIL::SigSpec subst_lvalue_from, subst_lvalue_to;
collect_lvalues(subst_lvalue_from, always, true, true); collect_lvalues(subst_lvalue_from, always.get(), true, true);
subst_lvalue_to = new_temp_signal(subst_lvalue_from); subst_lvalue_to = new_temp_signal(subst_lvalue_from);
subst_lvalue_map = subst_lvalue_from.to_sigbit_map(subst_lvalue_to); subst_lvalue_map = subst_lvalue_from.to_sigbit_map(subst_lvalue_to);
bool found_global_syncs = false; bool found_global_syncs = false;
bool found_anyedge_syncs = false; bool found_anyedge_syncs = false;
for (auto child : always->children) for (auto& child : always->children)
{ {
if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER &&
child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) { child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) {
@ -388,7 +388,7 @@ struct AST_INTERNAL::ProcessGenerator
// create syncs for the process // create syncs for the process
bool found_clocked_sync = false; bool found_clocked_sync = false;
for (auto child : always->children) for (auto& child : always->children)
if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) { if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) {
if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast && if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast &&
child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk))
@ -420,9 +420,9 @@ struct AST_INTERNAL::ProcessGenerator
} }
// process the AST // process the AST
for (auto child : always->children) for (auto& child : always->children)
if (child->type == AST_BLOCK) if (child->type == AST_BLOCK)
processAst(child); processAst(child.get());
for (auto sync: proc->syncs) for (auto sync: proc->syncs)
processMemWrites(sync); processMemWrites(sync);
@ -472,7 +472,7 @@ struct AST_INTERNAL::ProcessGenerator
for (int i = 0; i < GetSize(chunks); i++) for (int i = 0; i < GetSize(chunks); i++)
{ {
RTLIL::SigChunk &chunk = chunks[i]; RTLIL::SigChunk &chunk = chunks[i];
if (chunk.wire == NULL) if (chunk.wire == nullptr)
continue; continue;
std::string wire_name; std::string wire_name;
@ -484,7 +484,7 @@ struct AST_INTERNAL::ProcessGenerator
} while (current_module->wires_.count(wire_name) > 0); } while (current_module->wires_.count(wire_name) > 0);
RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width); RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width);
set_src_attr(wire, always); set_src_attr(wire, always.get());
chunk.wire = wire; chunk.wire = wire;
chunk.offset = 0; chunk.offset = 0;
@ -499,10 +499,10 @@ struct AST_INTERNAL::ProcessGenerator
switch (ast->type) switch (ast->type)
{ {
case AST_CASE: case AST_CASE:
for (auto child : ast->children) for (auto& child : ast->children)
if (child != ast->children[0]) { if (child != ast->children[0]) {
log_assert(child->type == AST_COND || child->type == AST_CONDX || child->type == AST_CONDZ); log_assert(child->type == AST_COND || child->type == AST_CONDX || child->type == AST_CONDZ);
collect_lvalues(reg, child, type_eq, type_le, false); collect_lvalues(reg, child.get(), type_eq, type_le, false);
} }
break; break;
@ -511,19 +511,19 @@ struct AST_INTERNAL::ProcessGenerator
case AST_CONDZ: case AST_CONDZ:
case AST_ALWAYS: case AST_ALWAYS:
case AST_INITIAL: case AST_INITIAL:
for (auto child : ast->children) for (auto& child : ast->children)
if (child->type == AST_BLOCK) if (child->type == AST_BLOCK)
collect_lvalues(reg, child, type_eq, type_le, false); collect_lvalues(reg, child.get(), type_eq, type_le, false);
break; break;
case AST_BLOCK: case AST_BLOCK:
for (auto child : ast->children) { for (auto& child : ast->children) {
if (child->type == AST_ASSIGN_EQ && type_eq) if (child->type == AST_ASSIGN_EQ && type_eq)
reg.append(child->children[0]->genRTLIL()); reg.append(child->children[0]->genRTLIL());
if (child->type == AST_ASSIGN_LE && type_le) if (child->type == AST_ASSIGN_LE && type_le)
reg.append(child->children[0]->genRTLIL()); reg.append(child->children[0]->genRTLIL());
if (child->type == AST_CASE || child->type == AST_BLOCK) if (child->type == AST_CASE || child->type == AST_BLOCK)
collect_lvalues(reg, child, type_eq, type_le, false); collect_lvalues(reg, child.get(), type_eq, type_le, false);
} }
break; break;
@ -583,8 +583,8 @@ struct AST_INTERNAL::ProcessGenerator
switch (ast->type) switch (ast->type)
{ {
case AST_BLOCK: case AST_BLOCK:
for (auto child : ast->children) for (auto& child : ast->children)
processAst(child); processAst(child.get());
break; break;
case AST_ASSIGN_EQ: case AST_ASSIGN_EQ:
@ -641,9 +641,9 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::SigSpec this_case_eq_rvalue = this_case_eq_lvalue; RTLIL::SigSpec this_case_eq_rvalue = this_case_eq_lvalue;
this_case_eq_rvalue.replace(subst_rvalue_map.stdmap()); this_case_eq_rvalue.replace(subst_rvalue_map.stdmap());
RTLIL::CaseRule *default_case = NULL; RTLIL::CaseRule *default_case = nullptr;
RTLIL::CaseRule *last_generated_case = NULL; RTLIL::CaseRule *last_generated_case = nullptr;
for (auto child : ast->children) for (auto& child : ast->children)
{ {
if (child == ast->children[0]) if (child == ast->children[0])
continue; continue;
@ -657,14 +657,14 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::CaseRule *backup_case = current_case; RTLIL::CaseRule *backup_case = current_case;
current_case = new RTLIL::CaseRule; current_case = new RTLIL::CaseRule;
set_src_attr(current_case, child); set_src_attr(current_case, child.get());
last_generated_case = current_case; last_generated_case = current_case;
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue); addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
for (auto node : child->children) { for (auto& node : child->children) {
if (node->type == AST_DEFAULT) if (node->type == AST_DEFAULT)
default_case = current_case; default_case = current_case;
else if (node->type == AST_BLOCK) else if (node->type == AST_BLOCK)
processAst(node); processAst(node.get());
else else
current_case->compare.push_back(node->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap())); current_case->compare.push_back(node->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap()));
} }
@ -678,7 +678,7 @@ struct AST_INTERNAL::ProcessGenerator
subst_rvalue_map.restore(); subst_rvalue_map.restore();
} }
if (last_generated_case != NULL && ast->get_bool_attribute(ID::full_case) && default_case == NULL) { if (last_generated_case != nullptr && ast->get_bool_attribute(ID::full_case) && default_case == nullptr) {
#if 0 #if 0
// this is a valid transformation, but as optimization it is premature. // this is a valid transformation, but as optimization it is premature.
// better: add a default case that assigns 'x' to everything, and let later // better: add a default case that assigns 'x' to everything, and let later
@ -690,7 +690,7 @@ struct AST_INTERNAL::ProcessGenerator
sw->cases.push_back(default_case); sw->cases.push_back(default_case);
#endif #endif
} else { } else {
if (default_case == NULL) { if (default_case == nullptr) {
default_case = new RTLIL::CaseRule; default_case = new RTLIL::CaseRule;
addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue); addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
} }
@ -760,7 +760,7 @@ struct AST_INTERNAL::ProcessGenerator
default_base = 16; default_base = 16;
std::vector<VerilogFmtArg> args; std::vector<VerilogFmtArg> args;
for (auto node : ast->children) { for (auto& node : ast->children) {
int width; int width;
bool is_signed; bool is_signed;
node->detectSignWidth(width, is_signed, nullptr); node->detectSignWidth(width, is_signed, nullptr);
@ -866,8 +866,8 @@ struct AST_INTERNAL::ProcessGenerator
break; break;
default: default:
// ast->dumpAst(NULL, "ast> "); // ast->dumpAst(nullptr, "ast> ");
// current_ast_mod->dumpAst(NULL, "mod> "); // current_ast_mod->dumpAst(nullptr, "mod> ");
log_abort(); log_abort();
} }
} }
@ -876,14 +876,14 @@ struct AST_INTERNAL::ProcessGenerator
{ {
// Maps per-memid AST_MEMWR IDs to indices in the mem_write_actions array. // Maps per-memid AST_MEMWR IDs to indices in the mem_write_actions array.
dict<std::pair<std::string, int>, int> port_map; dict<std::pair<std::string, int>, int> port_map;
for (auto child : always->children) for (auto& child : always->children)
if (child->type == AST_MEMWR) if (child->type == AST_MEMWR)
{ {
std::string memid = child->str; std::string memid = child->str;
int portid = child->children[3]->asInt(false); int portid = child->children[3]->asInt(false);
int cur_idx = GetSize(sync->mem_write_actions); int cur_idx = GetSize(sync->mem_write_actions);
RTLIL::MemWriteAction action; RTLIL::MemWriteAction action;
set_src_attr(&action, child); set_src_attr(&action, child.get());
action.memid = memid; action.memid = memid;
action.address = child->children[0]->genWidthRTLIL(-1, true, &subst_rvalue_map.stdmap()); action.address = child->children[0]->genWidthRTLIL(-1, true, &subst_rvalue_map.stdmap());
action.data = child->children[1]->genWidthRTLIL(current_module->memories[memid]->width, true, &subst_rvalue_map.stdmap()); action.data = child->children[1]->genWidthRTLIL(current_module->memories[memid]->width, true, &subst_rvalue_map.stdmap());
@ -971,11 +971,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
bool sub_sign_hint = true; bool sub_sign_hint = true;
int sub_width_hint = -1; int sub_width_hint = -1;
int this_width = 0; int this_width = 0;
AstNode *range = NULL; AstNode *range = nullptr;
AstNode *id_ast = NULL; AstNode *id_ast = nullptr;
bool local_found_real = false; bool local_found_real = false;
if (found_real == NULL) if (found_real == nullptr)
found_real = &local_found_real; found_real = &local_found_real;
switch (type) switch (type)
@ -1019,22 +1019,22 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
input_error("Failed to detect width for parameter %s!\n", str.c_str()); input_error("Failed to detect width for parameter %s!\n", str.c_str());
} }
if (children.size() != 0) if (children.size() != 0)
range = children[0]; range = children[0].get();
} else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) { } else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) {
if (!id_ast->range_valid) { if (!id_ast->range_valid) {
if (id_ast->type == AST_AUTOWIRE) if (id_ast->type == AST_AUTOWIRE)
this_width = 1; this_width = 1;
else { else {
// current_ast_mod->dumpAst(NULL, "mod> "); // current_ast_mod->dumpAst(nullptr, "mod> ");
// log("---\n"); // log("---\n");
// id_ast->dumpAst(NULL, "decl> "); // id_ast->dumpAst(nullptr, "decl> ");
// dumpAst(NULL, "ref> "); // dumpAst(nullptr, "ref> ");
input_error("Failed to detect width of signal access `%s'!\n", str.c_str()); input_error("Failed to detect width of signal access `%s'!\n", str.c_str());
} }
} else { } else {
this_width = id_ast->range_left - id_ast->range_right + 1; this_width = id_ast->range_left - id_ast->range_right + 1;
if (children.size() != 0) if (children.size() != 0)
range = children[0]; range = children[0].get();
} }
} else if (id_ast->type == AST_GENVAR) { } else if (id_ast->type == AST_GENVAR) {
this_width = 32; this_width = 32;
@ -1043,26 +1043,23 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
input_error("Failed to detect width of memory access `%s'!\n", str.c_str()); input_error("Failed to detect width of memory access `%s'!\n", str.c_str());
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1; this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
if (children.size() > 1) if (children.size() > 1)
range = children[1]; range = children[1].get();
} else if (id_ast->type == AST_STRUCT_ITEM || id_ast->type == AST_STRUCT || id_ast->type == AST_UNION) { } else if (id_ast->type == AST_STRUCT_ITEM || id_ast->type == AST_STRUCT || id_ast->type == AST_UNION) {
AstNode *tmp_range = make_index_range(id_ast); auto tmp_range = make_index_range(id_ast);
this_width = tmp_range->range_left - tmp_range->range_right + 1; this_width = tmp_range->range_left - tmp_range->range_right + 1;
delete tmp_range;
} else } else
input_error("Failed to detect width for identifier %s!\n", str.c_str()); input_error("Failed to detect width for identifier %s!\n", str.c_str());
if (range) { if (range) {
if (range->children.size() == 1) if (range->children.size() == 1)
this_width = 1; this_width = 1;
else if (!range->range_valid) { else if (!range->range_valid) {
AstNode *left_at_zero_ast = children[0]->children[0]->clone_at_zero(); auto left_at_zero_ast = children[0]->children[0]->clone_at_zero();
AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone(); auto right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone();
while (left_at_zero_ast->simplify(true, 1, -1, false)) { } while (left_at_zero_ast->simplify(true, 1, -1, false)) { }
while (right_at_zero_ast->simplify(true, 1, -1, false)) { } while (right_at_zero_ast->simplify(true, 1, -1, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
delete left_at_zero_ast;
delete right_at_zero_ast;
} else } else
this_width = range->range_left - range->range_right + 1; this_width = range->range_left - range->range_right + 1;
sign_hint = false; sign_hint = false;
@ -1106,7 +1103,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
break; break;
case AST_CONCAT: case AST_CONCAT:
for (auto child : children) { for (auto& child : children) {
sub_width_hint = 0; sub_width_hint = 0;
sub_sign_hint = true; sub_sign_hint = true;
child->detectSignWidthWorker(sub_width_hint, sub_sign_hint); child->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
@ -1135,7 +1132,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_BIT_OR: case AST_BIT_OR:
case AST_BIT_XOR: case AST_BIT_XOR:
case AST_BIT_XNOR: case AST_BIT_XNOR:
for (auto child : children) for (auto& child : children)
child->detectSignWidthWorker(width_hint, sign_hint, found_real); child->detectSignWidthWorker(width_hint, sign_hint, found_real);
break; break;
@ -1175,7 +1172,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_MUL: case AST_MUL:
case AST_DIV: case AST_DIV:
case AST_MOD: case AST_MOD:
for (auto child : children) for (auto& child : children)
child->detectSignWidthWorker(width_hint, sign_hint, found_real); child->detectSignWidthWorker(width_hint, sign_hint, found_real);
break; break;
@ -1216,12 +1213,13 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
width_hint = max(width_hint, sub_width_hint); width_hint = max(width_hint, sub_width_hint);
sign_hint &= sub_sign_hint; sign_hint &= sub_sign_hint;
}; };
visit_case_expr(children[0]); visit_case_expr(children[0].get());
for (size_t i = 1; i < children.size(); i++) { for (size_t i = 1; i < children.size(); i++) {
AstNode *child = children[i]; AstNode *child = children[i].get();
for (AstNode *v : child->children) for (auto& v : child->children) {
if (v->type != AST_DEFAULT && v->type != AST_BLOCK) if (v->type != AST_DEFAULT && v->type != AST_BLOCK)
visit_case_expr(v); visit_case_expr(v.get());
}
} }
break; break;
} }
@ -1269,9 +1267,9 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (func->type != AST_FUNCTION) if (func->type != AST_FUNCTION)
input_error("Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str()); input_error("Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str());
const AstNode *wire = nullptr; const AstNode *wire = nullptr;
for (const AstNode *child : func->children) for (const auto& child : func->children)
if (child->str == func->str) { if (child->str == func->str) {
wire = child; wire = child.get();
break; break;
} }
log_assert(wire && wire->type == AST_WIRE); log_assert(wire && wire->type == AST_WIRE);
@ -1280,10 +1278,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (!wire->children.empty()) if (!wire->children.empty())
{ {
log_assert(wire->children.size() == 1); log_assert(wire->children.size() == 1);
const AstNode *range = wire->children.at(0); const AstNode *range = wire->children.at(0).get();
log_assert(range->type == AST_RANGE && range->children.size() == 2); log_assert(range->type == AST_RANGE && range->children.size() == 2);
AstNode *left = range->children.at(0)->clone(); auto left = range->children.at(0)->clone();
AstNode *right = range->children.at(1)->clone(); auto right = range->children.at(1)->clone();
left->set_in_param_flag(true); left->set_in_param_flag(true);
right->set_in_param_flag(true); right->set_in_param_flag(true);
while (left->simplify(true, 1, -1, false)) { } while (left->simplify(true, 1, -1, false)) { }
@ -1292,8 +1290,6 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
input_error("Function %s has non-constant width!", input_error("Function %s has non-constant width!",
RTLIL::unescape_id(str).c_str()); RTLIL::unescape_id(str).c_str());
result_width = abs(int(left->asInt(true) - right->asInt(true))); result_width = abs(int(left->asInt(true) - right->asInt(true)));
delete left;
delete right;
} }
width_hint = max(width_hint, result_width); width_hint = max(width_hint, result_width);
break; break;
@ -1306,6 +1302,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
for (auto f : log_files) for (auto f : log_files)
current_scope_ast->dumpAst(f, "verilog-ast> "); current_scope_ast->dumpAst(f, "verilog-ast> ");
input_error("Don't know how to detect sign and width for %s node!\n", type2str(type).c_str()); input_error("Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());
} }
if (*found_real) if (*found_real)
@ -1517,11 +1514,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// shifter cell is created and the output signal of this cell is returned // shifter cell is created and the output signal of this cell is returned
case AST_IDENTIFIER: case AST_IDENTIFIER:
{ {
RTLIL::Wire *wire = NULL; RTLIL::Wire *wire = nullptr;
RTLIL::SigChunk chunk; RTLIL::SigChunk chunk;
bool is_interface = false; bool is_interface = false;
AST::AstNode *member_node = NULL; AST::AstNode *member_node = nullptr;
int add_undef_bits_msb = 0; int add_undef_bits_msb = 0;
int add_undef_bits_lsb = 0; int add_undef_bits_lsb = 0;
@ -1608,14 +1605,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
} }
if (!children[0]->range_valid) { if (!children[0]->range_valid) {
AstNode *left_at_zero_ast = children[0]->children[0]->clone_at_zero(); auto left_at_zero_ast = children[0]->children[0]->clone_at_zero();
AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone(); auto right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone();
while (left_at_zero_ast->simplify(true, 1, -1, false)) { } while (left_at_zero_ast->simplify(true, 1, -1, false)) { }
while (right_at_zero_ast->simplify(true, 1, -1, false)) { } while (right_at_zero_ast->simplify(true, 1, -1, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT) if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str()); input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ? auto fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
children[0]->children[1]->clone() : children[0]->children[0]->clone()); children[0]->children[1]->clone() : children[0]->children[0]->clone());
fake_ast->children[0]->delete_children(); fake_ast->children[0]->delete_children();
if (member_node) if (member_node)
@ -1637,9 +1634,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (GetSize(shift_val) >= 32) if (GetSize(shift_val) >= 32)
fake_ast->children[1]->is_signed = true; fake_ast->children[1]->is_signed = true;
RTLIL::SigSpec sig = binop2rtlil(fake_ast, ID($shiftx), width, fake_ast->children[0]->genRTLIL(), shift_val); RTLIL::SigSpec sig = binop2rtlil(fake_ast, ID($shiftx), width, fake_ast->children[0]->genRTLIL(), shift_val);
delete left_at_zero_ast;
delete right_at_zero_ast;
delete fake_ast;
return sig; return sig;
} else { } else {
chunk.width = children[0]->range_left - children[0]->range_right + 1; chunk.width = children[0]->range_left - children[0]->range_right + 1;
@ -2092,7 +2086,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
cell->set_bool_attribute(ID::module_not_derived); cell->set_bool_attribute(ID::module_not_derived);
for (auto it = children.begin(); it != children.end(); it++) { for (auto it = children.begin(); it != children.end(); it++) {
AstNode *child = *it; AstNode *child = it->get();
if (child->type == AST_CELLTYPE) { if (child->type == AST_CELLTYPE) {
cell->type = child->str; cell->type = child->str;
if (flag_icells && cell->type.begins_with("\\$")) if (flag_icells && cell->type.begins_with("\\$"))
@ -2101,7 +2095,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
} }
if (child->type == AST_PARASET) { if (child->type == AST_PARASET) {
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]; 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(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);
@ -2114,7 +2108,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (child->type == AST_ARGUMENT) { if (child->type == AST_ARGUMENT) {
RTLIL::SigSpec sig; RTLIL::SigSpec sig;
if (child->children.size() > 0) { if (child->children.size() > 0) {
AstNode *arg = child->children[0]; AstNode *arg = child->children[0].get();
int local_width_hint = -1; int local_width_hint = -1;
bool local_sign_hint = false; bool local_sign_hint = false;
// don't inadvertently attempt to detect the width of interfaces // don't inadvertently attempt to detect the width of interfaces
@ -2186,16 +2180,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// use ProcessGenerator for always blocks // use ProcessGenerator for always blocks
case AST_ALWAYS: { case AST_ALWAYS: {
AstNode *always = this->clone(); auto always = this->clone();
ProcessGenerator generator(always); ProcessGenerator generator(std::move(always));
ignoreThisSignalsInInitial.append(generator.outputSignals); ignoreThisSignalsInInitial.append(generator.outputSignals);
delete always;
} break; } break;
case AST_INITIAL: { case AST_INITIAL: {
AstNode *always = this->clone(); auto always = this->clone();
ProcessGenerator generator(always, ignoreThisSignalsInInitial); ProcessGenerator generator(std::move(always), ignoreThisSignalsInInitial);
delete always;
} break; } break;
case AST_TECALL: { case AST_TECALL: {

File diff suppressed because it is too large Load diff

View file

@ -2,3 +2,6 @@ verilog_lexer.cc
verilog_parser.output verilog_parser.output
verilog_parser.tab.cc verilog_parser.tab.cc
verilog_parser.tab.hh verilog_parser.tab.hh
position.hh
location.hh
stack.hh

View file

@ -9,6 +9,7 @@ frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y
$(P) $(BISON) -Wall -Werror -o $@ -d -r all -b frontends/verilog/verilog_parser $< $(P) $(BISON) -Wall -Werror -o $@ -d -r all -b frontends/verilog/verilog_parser $<
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_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 $@)

View file

@ -43,6 +43,10 @@ YOSYS_NAMESPACE_BEGIN
using namespace AST; using namespace AST;
static int get_line_num() {
// TODO
return 999;
}
// divide an arbitrary length decimal number by two and return the rest // divide an arbitrary length decimal number by two and return the rest
static int my_decimal_div_by_two(std::vector<uint8_t> &digits) static int my_decimal_div_by_two(std::vector<uint8_t> &digits)
{ {
@ -148,10 +152,10 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
} }
// convert the Verilog code for a constant to an AST node // convert the Verilog code for a constant to an AST node
AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn_z) std::unique_ptr<AstNode> VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn_z)
{ {
if (warn_z) { if (warn_z) {
AstNode *ret = const2ast(code, case_type); auto ret = const2ast(code, case_type);
if (ret != nullptr && std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end()) if (ret != nullptr && std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end())
log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n", log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n",
current_filename.c_str(), get_line_num()); current_filename.c_str(), get_line_num());
@ -172,7 +176,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
ch = ch >> 1; ch = ch >> 1;
} }
} }
AstNode *ast = AstNode::mkconst_bits(data, false); auto ast = AstNode::mkconst_bits(data, false);
ast->str = code; ast->str = code;
return ast; return ast;
} }

View file

@ -48,11 +48,11 @@ 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()); log_file_error(node->filename, node->location.first_line, "Found DPI function %s.\n", node->str.c_str());
for (auto child : node->children) for (auto& child : node->children)
error_on_dpi_function(child); error_on_dpi_function(child.get());
} }
static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std::vector<AST::AstNode *> &package_list) static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std::vector<std::unique_ptr<AST::AstNode>> &package_list)
{ {
// prime the parser's user type lookup table with the package qualified names // prime the parser's user type lookup table with the package qualified names
// of typedefed names in the packages seen so far. // of typedefed names in the packages seen so far.
@ -61,14 +61,16 @@ static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std
for (const auto &node: pkg->children) { for (const auto &node: pkg->children) {
if (node->type == AST::AST_TYPEDEF) { if (node->type == AST::AST_TYPEDEF) {
std::string s = pkg->str + "::" + node->str.substr(1); std::string s = pkg->str + "::" + node->str.substr(1);
user_types[s] = node; user_types[s] = node.get();
} }
} }
} }
} }
struct VerilogFrontend : public Frontend { struct VerilogFrontend : public Frontend {
VerilogFrontend() : Frontend("verilog", "read modules from Verilog file") { } VerilogLexer lexer;
frontend_verilog_yy::parser parser;
VerilogFrontend() : Frontend("verilog", "read modules from Verilog file"), lexer(), parser(&lexer) { }
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---|
@ -266,12 +268,14 @@ struct VerilogFrontend : public Frontend {
bool flag_noblackbox = false; bool flag_noblackbox = false;
bool flag_nowb = false; bool flag_nowb = false;
bool flag_nosynthesis = false; bool flag_nosynthesis = false;
bool flag_yydebug = false;
define_map_t defines_map; define_map_t defines_map;
std::list<std::string> include_dirs; std::list<std::string> include_dirs;
std::list<std::string> attributes; std::list<std::string> attributes;
frontend_verilog_yydebug = false; lexer.set_debug(false);
parser.set_debug_level(0);
sv_mode = false; sv_mode = false;
formal_mode = false; formal_mode = false;
noassert_mode = false; noassert_mode = false;
@ -329,7 +333,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;
frontend_verilog_yydebug = true; lexer.set_debug(true);
parser.set_debug_level(1);
continue; continue;
} }
if (arg == "-dump_ast1") { if (arg == "-dump_ast1") {
@ -357,7 +362,7 @@ struct VerilogFrontend : public Frontend {
continue; continue;
} }
if (arg == "-yydebug") { if (arg == "-yydebug") {
frontend_verilog_yydebug = true; flag_yydebug = true;
continue; continue;
} }
if (arg == "-nolatches") { if (arg == "-nolatches") {
@ -480,8 +485,6 @@ struct VerilogFrontend : public Frontend {
formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str()); formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str());
AST::current_filename = filename; AST::current_filename = filename;
AST::set_line_num = &frontend_verilog_yyset_lineno;
AST::get_line_num = &frontend_verilog_yyget_lineno;
current_ast = new AST::AstNode(AST::AST_DESIGN); current_ast = new AST::AstNode(AST::AST_DESIGN);
@ -499,9 +502,9 @@ struct VerilogFrontend : public Frontend {
add_package_types(pkg_user_types, design->verilog_packages); add_package_types(pkg_user_types, design->verilog_packages);
UserTypeMap global_types_map; UserTypeMap global_types_map;
for (auto def : design->verilog_globals) { for (auto& def : design->verilog_globals) {
if (def->type == AST::AST_TYPEDEF) { if (def->type == AST::AST_TYPEDEF) {
global_types_map[def->str] = def; global_types_map[def->str] = def.get();
} }
} }
@ -511,10 +514,16 @@ 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
user_type_stack.push_back(UserTypeMap()); user_type_stack.push_back(UserTypeMap());
frontend_verilog_yyset_lineno(1); parser.~parser();
frontend_verilog_yyrestart(NULL); lexer.~VerilogLexer();
frontend_verilog_yyparse(); new (&lexer) VerilogLexer();
frontend_verilog_yylex_destroy(); new (&parser) frontend_verilog_yy::parser(&lexer);
if (flag_yydebug) {
lexer.set_debug(true);
parser.set_debug_level(1);
}
parser.parse();
// frontend_verilog_yyset_lineno(1);
for (auto &child : current_ast->children) { for (auto &child : current_ast->children) {
if (child->type == AST::AST_MODULE) if (child->type == AST::AST_MODULE)
@ -759,10 +768,8 @@ struct VerilogFileList : public Pass {
#endif #endif
YOSYS_NAMESPACE_END
// the yyerror function used by bison to report parser errors // the yyerror function used by bison to report parser errors
void frontend_verilog_yyerror(char const *fmt, ...) void VERILOG_FRONTEND::frontend_verilog_yyerror(char const *fmt, ...)
{ {
va_list ap; va_list ap;
char buffer[1024]; char buffer[1024];
@ -771,7 +778,11 @@ void frontend_verilog_yyerror(char const *fmt, ...)
p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap); p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
va_end(ap); va_end(ap);
p += snprintf(p, buffer + sizeof(buffer) - p, "\n"); p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
YOSYS_NAMESPACE_PREFIX log_file_error(YOSYS_NAMESPACE_PREFIX AST::current_filename, frontend_verilog_yyget_lineno(), // TODO fix loc
"%s", buffer); YOSYS_NAMESPACE_PREFIX log_file_error(YOSYS_NAMESPACE_PREFIX AST::current_filename, 999,
"%s", buffer);
exit(1); exit(1);
} }
YOSYS_NAMESPACE_END
std::string fmt(const char *format, ...) YS_ATTRIBUTE(format(printf, 1, 2));

View file

@ -31,6 +31,18 @@
#include "kernel/yosys.h" #include "kernel/yosys.h"
#include "frontends/ast/ast.h" #include "frontends/ast/ast.h"
#if ! defined(yyFlexLexerOnce)
#define yyFlexLexer frontend_verilog_yyFlexLexer
#include <FlexLexer.h>
#endif
YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND {
class VerilogLexer;
};
YOSYS_NAMESPACE_END
#include "frontends/verilog/verilog_parser.tab.hh"
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <list> #include <list>
@ -43,7 +55,7 @@ namespace VERILOG_FRONTEND
extern struct AST::AstNode *current_ast; extern struct AST::AstNode *current_ast;
// this function converts a Verilog constant to an AST_CONSTANT node // this function converts a Verilog constant to an AST_CONSTANT node
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);
// names of locally typedef'ed types in a stack // names of locally typedef'ed types in a stack
typedef std::map<std::string, AST::AstNode*> UserTypeMap; typedef std::map<std::string, AST::AstNode*> UserTypeMap;
@ -84,17 +96,32 @@ namespace VERILOG_FRONTEND
// lexer input stream // lexer input stream
extern std::istream *lexin; extern std::istream *lexin;
} using parser = frontend_verilog_yy::parser;
class VerilogLexer : public frontend_verilog_yyFlexLexer {
public:
VerilogLexer(std::istream* in = nullptr) : frontend_verilog_yyFlexLexer(in) {}
~VerilogLexer() override {}
// autogenerated body due to YY_DECL
parser::symbol_type nextToken();
// get rid of override virtual function warning
using FlexLexer::yylex;
parser::symbol_type terminate() {
return parser::make_FRONTEND_VERILOG_YYEOF(out_loc);
}
parser::location_type out_loc;
private:
std::vector<std::string> fn_stack;
std::vector<int> ln_stack;
parser::location_type real_loc;
parser::location_type old_loc;
};
extern void frontend_verilog_yyerror(char const *fmt, ...);
// parser::symbol_type frontend_verilog_yylex(VerilogLexer& lexer) {
// return lexer.nextToken();
// };
};
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END
// the usual bison/flex stuff
extern int frontend_verilog_yydebug;
void frontend_verilog_yyerror(char const *fmt, ...);
void frontend_verilog_yyrestart(FILE *f);
int frontend_verilog_yyparse(void);
int frontend_verilog_yylex_destroy(void);
int frontend_verilog_yyget_lineno(void);
void frontend_verilog_yyset_lineno (int);
#endif #endif

View file

@ -32,7 +32,16 @@
* *
*/ */
%option c++
%option yyclass="VerilogLexer"
%option noyywrap
%option nounput
%option yylineno
%option prefix="frontend_verilog_yy"
%{ %{
//%option bison-locations
//%option bison-bridge
#ifdef __clang__ #ifdef __clang__
// bison generates code using the 'register' storage class specifier // bison generates code using the 'register' storage class specifier
@ -41,85 +50,113 @@
#pragma clang diagnostic ignored "-Wmisleading-indentation" #pragma clang diagnostic ignored "-Wmisleading-indentation"
#endif #endif
#include "kernel/log.h"
#include "frontends/verilog/verilog_frontend.h" #include "frontends/verilog/verilog_frontend.h"
#include "frontends/ast/ast.h" #include "frontends/ast/ast.h"
#include "verilog_parser.tab.hh" #include "kernel/log.h"
#include <vector>
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
using namespace AST; using namespace AST;
using namespace VERILOG_FRONTEND; using namespace VERILOG_FRONTEND;
using parser = frontend_verilog_yy::parser;
#define YYSTYPE FRONTEND_VERILOG_YYSTYPE //#define YYSTYPE FRONTEND_VERILOG_YYSTYPE
#define YYLTYPE FRONTEND_VERILOG_YYLTYPE //#define YYLTYPE FRONTEND_VERILOG_YYLTYPE
YOSYS_NAMESPACE_BEGIN YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND { #undef YY_DECL
std::vector<std::string> fn_stack; #define YY_DECL parser::symbol_type VerilogLexer::nextToken()
std::vector<int> ln_stack;
YYLTYPE real_location; #undef yyterminate
YYLTYPE old_location; #define yyterminate() terminate()
}
YOSYS_NAMESPACE_END YOSYS_NAMESPACE_END
#define SV_KEYWORD(_tok) \ #define SV_KEYWORD(_tok) \
if (sv_mode) return _tok; \ if (sv_mode) return _tok; \
log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\ log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\
"recognized unless read_verilog is called with -sv!\n", yytext, \ "recognized unless read_verilog is called with -sv!\n", YYText(), \
AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); \ AST::current_filename.c_str(), yylineno); \
yylval->string = new std::string(std::string("\\") + yytext); \ string_t val = new std::string(std::string("\\") + YYText()); \
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
#define NON_KEYWORD() \ #define NON_KEYWORD() \
yylval->string = new std::string(std::string("\\") + yytext); \ string_t val = new std::string(std::string("\\") + YYText()); \
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
#define YY_INPUT(buf,result,max_size) \ #define YY_INPUT(buf,result,max_size) \
result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size) result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
#define YY_USER_ACTION \ #define YY_USER_ACTION \
old_location = real_location; \ old_loc = real_loc; \
real_location.first_line = real_location.last_line; \ real_loc.begin = real_loc.end; \
real_location.first_column = real_location.last_column; \ 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++; \
real_location.last_line++; \ real_loc.end.column = 1; \
real_location.last_column = 1; \ } \
} \ else { \
else { \ real_loc.end.column++; \
real_location.last_column++; \ } \
} \ }
} \
(*yylloc) = real_location;
#define YY_BREAK \ #define YY_BREAK \
(*yylloc) = old_location; \ out_loc = old_loc; \
break; break;
#undef YY_BUF_SIZE #undef YY_BUF_SIZE
#define YY_BUF_SIZE 65536 #define YY_BUF_SIZE 65536
extern int frontend_verilog_yylex(YYSTYPE *yylval_param, YYLTYPE *yyloc_param);
static bool isUserType(std::string &s) static bool isUserType(std::string &s)
{ {
// check current scope then outer scopes for a name // check current scope then outer scopes for a name
for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) { for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) {
if (it->count(s) > 0) { if (it->count(s) > 0) {
return true; return true;
} }
} }
return false; return false;
} }
%} parser::symbol_type char_tok(char c, parser::location_type loc) {
switch (c) {
case '!': return parser::make_TOK_EXCL(loc);
case '#': return parser::make_TOK_HASH(loc);
case '%': return parser::make_TOK_PERC(loc);
case '&': return parser::make_TOK_AMP(loc);
case '(': return parser::make_TOK_LPAREN(loc);
case ')': return parser::make_TOK_RPAREN(loc);
case '*': return parser::make_TOK_ASTER(loc);
case '+': return parser::make_TOK_PLUS(loc);
case ',': return parser::make_TOK_COMMA(loc);
case '-': return parser::make_TOK_MINUS(loc);
case '.': return parser::make_TOK_DOT(loc);
case '/': return parser::make_TOK_SLASH(loc);
case ':': return parser::make_TOK_COL(loc);
case ';': return parser::make_TOK_SEMICOL(loc);
case '<': return parser::make_TOK_LT(loc);
case '=': return parser::make_TOK_EQ(loc);
case '>': return parser::make_TOK_GT(loc);
case '?': return parser::make_TOK_QUE(loc);
case '@': return parser::make_TOK_AT(loc);
case '[': return parser::make_TOK_LBRA(loc);
case ']': return parser::make_TOK_RBRA(loc);
case '^': return parser::make_TOK_CARET(loc);
case '_': return parser::make_TOK_UNDER(loc);
case '{': return parser::make_TOK_LCURL(loc);
case '|': return parser::make_TOK_PIPE(loc);
case '}': return parser::make_TOK_RCURL(loc);
case '~': return parser::make_TOK_TILDE(loc);
case 'n': return parser::make_TOK_n(loc);
case 'p': return parser::make_TOK_p(loc);
case 'x': return parser::make_TOK_x(loc);
case 'z': return parser::make_TOK_z(loc);
case 0: return parser::make_FRONTEND_VERILOG_YYEOF(loc);
default:
std::cout << ".." << +c << "..\n"; return parser::make_ch_t(c, loc);
}
}
%option yylineno %}
%option noyywrap
%option nounput
%option bison-locations
%option bison-bridge
%option prefix="frontend_verilog_yy"
%x COMMENT %x COMMENT
%x STRING %x STRING
@ -134,47 +171,48 @@ FIXED_POINT_NUMBER_NO_DEC [0-9][0-9_]*[eE][-+]?[0-9_]+
TIME_SCALE_SUFFIX [munpf]?s TIME_SCALE_SUFFIX [munpf]?s
%% %%
// Initialise comment_caller to something to avoid a "maybe undefined" // Initialise comment_caller to something to avoid a "maybe undefined"
// warning from GCC. // warning from GCC.
int comment_caller = INITIAL; int comment_caller = INITIAL;
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* { <INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* {
fn_stack.push_back(current_filename); fn_stack.push_back(current_filename);
ln_stack.push_back(frontend_verilog_yyget_lineno()); ln_stack.push_back(yylineno);
current_filename = yytext+11; current_filename = YYText()+11;
if (!current_filename.empty() && current_filename.front() == '"') if (!current_filename.empty() && current_filename.front() == '"')
current_filename = current_filename.substr(1); current_filename = current_filename.substr(1);
if (!current_filename.empty() && current_filename.back() == '"') if (!current_filename.empty() && current_filename.back() == '"')
current_filename = current_filename.substr(0, current_filename.size()-1); current_filename = current_filename.substr(0, current_filename.size()-1);
frontend_verilog_yyset_lineno(0); yylineno = (0);
yylloc->first_line = yylloc->last_line = 0; out_loc.begin.line = out_loc.end.line = 0;
real_location.first_line = real_location.last_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 {
current_filename = fn_stack.back(); current_filename = fn_stack.back();
fn_stack.pop_back(); fn_stack.pop_back();
frontend_verilog_yyset_lineno(ln_stack.back()); yylineno = (ln_stack.back());
yylloc->first_line = yylloc->last_line = ln_stack.back(); out_loc.begin.line = out_loc.end.line = ln_stack.back();
real_location.first_line = real_location.last_line = ln_stack.back(); real_loc.begin.line = real_loc.end.line = ln_stack.back();
ln_stack.pop_back(); ln_stack.pop_back();
} }
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`line"[ \t]+[^ \t\r\n]+[ \t]+\"[^ \r\n]+\"[^\r\n]*\n { <INITIAL,SYNOPSYS_TRANSLATE_OFF>"`line"[ \t]+[^ \t\r\n]+[ \t]+\"[^ \r\n]+\"[^\r\n]*\n {
char *p = yytext + 5; const char *p = YYText() + 5;
while (*p == ' ' || *p == '\t') p++; while (*p == ' ' || *p == '\t') p++;
frontend_verilog_yyset_lineno(atoi(p)); yylineno = (atoi(p));
yylloc->first_line = yylloc->last_line = atoi(p); out_loc.begin.line = out_loc.end.line = atoi(p);
real_location.first_line = real_location.last_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++;
char *q = *p ? p + 1 : p; const char *q = *p ? p + 1 : p;
while (*q && *q != '"') q++; while (*q && *q != '"') q++;
current_filename = std::string(p).substr(1, q-p-1); current_filename = std::string(p).substr(1, q-p-1);
} }
"`file_notfound "[^\n]* { "`file_notfound "[^\n]* {
log_error("Can't open include file `%s'!\n", yytext + 15); log_error("Can't open include file `%s'!\n", YYText() + 15);
} }
"`timescale"[ \t]+[^ \t\r\n/]+[ \t]*"/"[ \t]*[^ \t\r\n]* /* ignore timescale directive */ "`timescale"[ \t]+[^ \t\r\n/]+[ \t]*"/"[ \t]*[^ \t\r\n]* /* ignore timescale directive */
@ -183,7 +221,7 @@ TIME_SCALE_SUFFIX [munpf]?s
"`endcelldefine"[^\n]* /* ignore `endcelldefine */ "`endcelldefine"[^\n]* /* ignore `endcelldefine */
"`default_nettype"[ \t]+[^ \t\r\n/]+ { "`default_nettype"[ \t]+[^ \t\r\n/]+ {
char *p = yytext; const char *p = YYText();
while (*p != 0 && *p != ' ' && *p != '\t') p++; while (*p != 0 && *p != ' ' && *p != '\t') p++;
while (*p == ' ' || *p == '\t') p++; while (*p == ' ' || *p == '\t') p++;
if (!strcmp(p, "none")) if (!strcmp(p, "none"))
@ -198,149 +236,149 @@ TIME_SCALE_SUFFIX [munpf]?s
"`endprotect"[^\n]* /* ignore `endprotect*/ "`endprotect"[^\n]* /* ignore `endprotect*/
"`"[a-zA-Z_$][a-zA-Z0-9_$]* { "`"[a-zA-Z_$][a-zA-Z0-9_$]* {
frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext); frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", YYText());
} }
"module" { return TOK_MODULE; } "module" { return parser::make_TOK_MODULE(out_loc); }
"endmodule" { return TOK_ENDMODULE; } "endmodule" { return parser::make_TOK_ENDMODULE(out_loc); }
"function" { return TOK_FUNCTION; } "function" { return parser::make_TOK_FUNCTION(out_loc); }
"endfunction" { return TOK_ENDFUNCTION; } "endfunction" { return parser::make_TOK_ENDFUNCTION(out_loc); }
"task" { return TOK_TASK; } "task" { return parser::make_TOK_TASK(out_loc); }
"endtask" { return TOK_ENDTASK; } "endtask" { return parser::make_TOK_ENDTASK(out_loc); }
"specify" { return specify_mode ? TOK_SPECIFY : TOK_IGNORED_SPECIFY; } "specify" { return specify_mode ? parser::make_TOK_SPECIFY(out_loc) : parser::make_TOK_IGNORED_SPECIFY(out_loc); }
"endspecify" { return TOK_ENDSPECIFY; } "endspecify" { return parser::make_TOK_ENDSPECIFY(out_loc); }
"specparam" { return TOK_SPECPARAM; } "specparam" { return parser::make_TOK_SPECPARAM(out_loc); }
"package" { SV_KEYWORD(TOK_PACKAGE); } "package" { SV_KEYWORD(parser::make_TOK_PACKAGE(out_loc)); }
"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); } "endpackage" { SV_KEYWORD(parser::make_TOK_ENDPACKAGE(out_loc)); }
"interface" { SV_KEYWORD(TOK_INTERFACE); } "interface" { SV_KEYWORD(parser::make_TOK_INTERFACE(out_loc)); }
"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); } "endinterface" { SV_KEYWORD(parser::make_TOK_ENDINTERFACE(out_loc)); }
"modport" { SV_KEYWORD(TOK_MODPORT); } "modport" { SV_KEYWORD(parser::make_TOK_MODPORT(out_loc)); }
"parameter" { return TOK_PARAMETER; } "parameter" { return parser::make_TOK_PARAMETER(out_loc); }
"localparam" { return TOK_LOCALPARAM; } "localparam" { return parser::make_TOK_LOCALPARAM(out_loc); }
"defparam" { return TOK_DEFPARAM; } "defparam" { return parser::make_TOK_DEFPARAM(out_loc); }
"assign" { return TOK_ASSIGN; } "assign" { return parser::make_TOK_ASSIGN(out_loc); }
"always" { return TOK_ALWAYS; } "always" { return parser::make_TOK_ALWAYS(out_loc); }
"initial" { return TOK_INITIAL; } "initial" { return parser::make_TOK_INITIAL(out_loc); }
"begin" { return TOK_BEGIN; } "begin" { return parser::make_TOK_BEGIN(out_loc); }
"end" { return TOK_END; } "end" { return parser::make_TOK_END(out_loc); }
"if" { return TOK_IF; } "if" { return parser::make_TOK_IF(out_loc); }
"else" { return TOK_ELSE; } "else" { return parser::make_TOK_ELSE(out_loc); }
"for" { return TOK_FOR; } "for" { return parser::make_TOK_FOR(out_loc); }
"posedge" { return TOK_POSEDGE; } "posedge" { return parser::make_TOK_POSEDGE(out_loc); }
"negedge" { return TOK_NEGEDGE; } "negedge" { return parser::make_TOK_NEGEDGE(out_loc); }
"or" { return TOK_OR; } "or" { return parser::make_TOK_OR(out_loc); }
"case" { return TOK_CASE; } "case" { return parser::make_TOK_CASE(out_loc); }
"casex" { return TOK_CASEX; } "casex" { return parser::make_TOK_CASEX(out_loc); }
"casez" { return TOK_CASEZ; } "casez" { return parser::make_TOK_CASEZ(out_loc); }
"endcase" { return TOK_ENDCASE; } "endcase" { return parser::make_TOK_ENDCASE(out_loc); }
"default" { return TOK_DEFAULT; } "default" { return parser::make_TOK_DEFAULT(out_loc); }
"generate" { return TOK_GENERATE; } "generate" { return parser::make_TOK_GENERATE(out_loc); }
"endgenerate" { return TOK_ENDGENERATE; } "endgenerate" { return parser::make_TOK_ENDGENERATE(out_loc); }
"while" { return TOK_WHILE; } "while" { return parser::make_TOK_WHILE(out_loc); }
"repeat" { return TOK_REPEAT; } "repeat" { return parser::make_TOK_REPEAT(out_loc); }
"automatic" { return TOK_AUTOMATIC; } "automatic" { return parser::make_TOK_AUTOMATIC(out_loc); }
"unique" { SV_KEYWORD(TOK_UNIQUE); } "unique" { SV_KEYWORD(parser::make_TOK_UNIQUE(out_loc)); }
"unique0" { SV_KEYWORD(TOK_UNIQUE0); } "unique0" { SV_KEYWORD(parser::make_TOK_UNIQUE0(out_loc)); }
"priority" { SV_KEYWORD(TOK_PRIORITY); } "priority" { SV_KEYWORD(parser::make_TOK_PRIORITY(out_loc)); }
"always_comb" { SV_KEYWORD(TOK_ALWAYS_COMB); } "always_comb" { SV_KEYWORD(parser::make_TOK_ALWAYS_COMB(out_loc)); }
"always_ff" { SV_KEYWORD(TOK_ALWAYS_FF); } "always_ff" { SV_KEYWORD(parser::make_TOK_ALWAYS_FF(out_loc)); }
"always_latch" { SV_KEYWORD(TOK_ALWAYS_LATCH); } "always_latch" { SV_KEYWORD(parser::make_TOK_ALWAYS_LATCH(out_loc)); }
/* use special token for labels on assert, assume, cover, and restrict because it's insanley complex /* use special token for labels on assert, assume, cover, and restrict because it's insanley complex
to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
global state.. its a mess) */ global state.. its a mess) */
[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] { [a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
if (!strcmp(yytext, "default")) if (!strcmp(YYText(), "default"))
return TOK_DEFAULT; return parser::make_TOK_DEFAULT(out_loc);
yylval->string = new std::string(std::string("\\") + yytext); string_t val = new std::string(std::string("\\") + YYText());
return TOK_SVA_LABEL; return parser::make_TOK_SVA_LABEL(val, out_loc);
} }
"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); } "assert" { if (formal_mode) return parser::make_TOK_ASSERT(out_loc); SV_KEYWORD(parser::make_TOK_ASSERT(out_loc)); }
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); } "assume" { if (formal_mode) return parser::make_TOK_ASSUME(out_loc); SV_KEYWORD(parser::make_TOK_ASSUME(out_loc)); }
"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); } "cover" { if (formal_mode) return parser::make_TOK_COVER(out_loc); SV_KEYWORD(parser::make_TOK_COVER(out_loc)); }
"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); } "restrict" { if (formal_mode) return parser::make_TOK_RESTRICT(out_loc); SV_KEYWORD(parser::make_TOK_RESTRICT(out_loc)); }
"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); } "property" { if (formal_mode) return parser::make_TOK_PROPERTY(out_loc); SV_KEYWORD(parser::make_TOK_PROPERTY(out_loc)); }
"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); } "rand" { if (formal_mode) return parser::make_TOK_RAND(out_loc); SV_KEYWORD(parser::make_TOK_RAND(out_loc)); }
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); } "const" { if (formal_mode) return parser::make_TOK_CONST(out_loc); SV_KEYWORD(parser::make_TOK_CONST(out_loc)); }
"checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); } "checker" { if (formal_mode) return parser::make_TOK_CHECKER(out_loc); SV_KEYWORD(parser::make_TOK_CHECKER(out_loc)); }
"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); } "endchecker" { if (formal_mode) return parser::make_TOK_ENDCHECKER(out_loc); SV_KEYWORD(parser::make_TOK_ENDCHECKER(out_loc)); }
"bind" { if (formal_mode) return TOK_BIND; SV_KEYWORD(TOK_BIND); } "bind" { if (formal_mode) return parser::make_TOK_BIND(out_loc); SV_KEYWORD(parser::make_TOK_BIND(out_loc)); }
"final" { SV_KEYWORD(TOK_FINAL); } "final" { SV_KEYWORD(parser::make_TOK_FINAL(out_loc)); }
"logic" { SV_KEYWORD(TOK_LOGIC); } "logic" { SV_KEYWORD(parser::make_TOK_LOGIC(out_loc)); }
"var" { SV_KEYWORD(TOK_VAR); } "var" { SV_KEYWORD(parser::make_TOK_VAR(out_loc)); }
"bit" { SV_KEYWORD(TOK_LOGIC); } "bit" { SV_KEYWORD(parser::make_TOK_LOGIC(out_loc)); }
"int" { SV_KEYWORD(TOK_INT); } "int" { SV_KEYWORD(parser::make_TOK_INT(out_loc)); }
"byte" { SV_KEYWORD(TOK_BYTE); } "byte" { SV_KEYWORD(parser::make_TOK_BYTE(out_loc)); }
"shortint" { SV_KEYWORD(TOK_SHORTINT); } "shortint" { SV_KEYWORD(parser::make_TOK_SHORTINT(out_loc)); }
"longint" { SV_KEYWORD(TOK_LONGINT); } "longint" { SV_KEYWORD(parser::make_TOK_LONGINT(out_loc)); }
"void" { SV_KEYWORD(TOK_VOID); } "void" { SV_KEYWORD(parser::make_TOK_VOID(out_loc)); }
"eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } "eventually" { if (formal_mode) return parser::make_TOK_EVENTUALLY(out_loc); SV_KEYWORD(parser::make_TOK_EVENTUALLY(out_loc)); }
"s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); } "s_eventually" { if (formal_mode) return parser::make_TOK_EVENTUALLY(out_loc); SV_KEYWORD(parser::make_TOK_EVENTUALLY(out_loc)); }
"input" { return TOK_INPUT; } "input" { return parser::make_TOK_INPUT(out_loc); }
"output" { return TOK_OUTPUT; } "output" { return parser::make_TOK_OUTPUT(out_loc); }
"inout" { return TOK_INOUT; } "inout" { return parser::make_TOK_INOUT(out_loc); }
"wire" { return TOK_WIRE; } "wire" { return parser::make_TOK_WIRE(out_loc); }
"tri" { return TOK_WIRE; } "tri" { return parser::make_TOK_WIRE(out_loc); }
"wor" { return TOK_WOR; } "wor" { return parser::make_TOK_WOR(out_loc); }
"trior" { return TOK_WOR; } "trior" { return parser::make_TOK_WOR(out_loc); }
"wand" { return TOK_WAND; } "wand" { return parser::make_TOK_WAND(out_loc); }
"triand" { return TOK_WAND; } "triand" { return parser::make_TOK_WAND(out_loc); }
"reg" { return TOK_REG; } "reg" { return parser::make_TOK_REG(out_loc); }
"integer" { return TOK_INTEGER; } "integer" { return parser::make_TOK_INTEGER(out_loc); }
"signed" { return TOK_SIGNED; } "signed" { return parser::make_TOK_SIGNED(out_loc); }
"unsigned" { SV_KEYWORD(TOK_UNSIGNED); } "unsigned" { SV_KEYWORD(parser::make_TOK_UNSIGNED(out_loc)); }
"genvar" { return TOK_GENVAR; } "genvar" { return parser::make_TOK_GENVAR(out_loc); }
"real" { return TOK_REAL; } "real" { return parser::make_TOK_REAL(out_loc); }
"enum" { SV_KEYWORD(TOK_ENUM); } "enum" { SV_KEYWORD(parser::make_TOK_ENUM(out_loc)); }
"typedef" { SV_KEYWORD(TOK_TYPEDEF); } "typedef" { SV_KEYWORD(parser::make_TOK_TYPEDEF(out_loc)); }
"struct" { SV_KEYWORD(TOK_STRUCT); } "struct" { SV_KEYWORD(parser::make_TOK_STRUCT(out_loc)); }
"union" { SV_KEYWORD(TOK_UNION); } "union" { SV_KEYWORD(parser::make_TOK_UNION(out_loc)); }
"packed" { SV_KEYWORD(TOK_PACKED); } "packed" { SV_KEYWORD(parser::make_TOK_PACKED(out_loc)); }
{UNSIGNED_NUMBER} { {UNSIGNED_NUMBER} {
yylval->string = new std::string(yytext); string_t val = new std::string(YYText());
return TOK_CONSTVAL; return parser::make_TOK_CONSTVAL(val, out_loc);
} }
\'[01zxZX] { \'[01zxZX] {
yylval->string = new std::string(yytext); string_t val = new std::string(YYText());
return TOK_UNBASED_UNSIZED_CONSTVAL; return parser::make_TOK_UNBASED_UNSIZED_CONSTVAL(val, out_loc);
} }
\'[sS]?[bodhBODH] { \'[sS]?[bodhBODH] {
BEGIN(BASED_CONST); BEGIN(BASED_CONST);
yylval->string = new std::string(yytext); string_t val = new std::string(YYText());
return TOK_BASE; return parser::make_TOK_BASE(val, out_loc);
} }
<BASED_CONST>[0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* { <BASED_CONST>[0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* {
BEGIN(0); BEGIN(0);
yylval->string = new std::string(yytext); string_t val = new std::string(YYText());
return TOK_BASED_CONSTVAL; return parser::make_TOK_BASED_CONSTVAL(val, out_loc);
} }
{FIXED_POINT_NUMBER_DEC} { {FIXED_POINT_NUMBER_DEC} {
yylval->string = new std::string(yytext); string_t val = new std::string(YYText());
return TOK_REALVAL; return parser::make_TOK_REALVAL(val, out_loc);
} }
{FIXED_POINT_NUMBER_NO_DEC} { {FIXED_POINT_NUMBER_NO_DEC} {
yylval->string = new std::string(yytext); string_t val = new std::string(YYText());
return TOK_REALVAL; return parser::make_TOK_REALVAL(val, out_loc);
} }
\" { BEGIN(STRING); } \" { BEGIN(STRING); }
<STRING>\\. { yymore(); real_location = old_location; } <STRING>\\. { yymore(); real_loc = old_loc; }
<STRING>\" { <STRING>\" {
BEGIN(0); BEGIN(0);
char *yystr = strdup(yytext); char *yystr = strdup(YYText());
yystr[strlen(yytext) - 1] = 0; yystr[strlen(YYText()) - 1] = 0;
int i = 0, j = 0; int i = 0, j = 0;
while (yystr[i]) { while (yystr[i]) {
if (yystr[i] == '\\' && yystr[i + 1]) { if (yystr[i] == '\\' && yystr[i + 1]) {
@ -372,72 +410,72 @@ TIME_SCALE_SUFFIX [munpf]?s
yystr[j++] = yystr[i++]; yystr[j++] = yystr[i++];
} }
yystr[j] = 0; yystr[j] = 0;
yylval->string = new std::string(yystr, j); string_t val = new std::string(yystr, j);
free(yystr); free(yystr);
return TOK_STRING; return parser::make_TOK_STRING(val, out_loc);
} }
<STRING>. { yymore(); real_location = old_location; } <STRING>. { yymore(); real_loc = old_loc; }
and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 { and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
yylval->string = new std::string(yytext); auto val = new std::string(YYText());
return TOK_PRIMITIVE; return parser::make_TOK_PRIMITIVE(val, out_loc);
} }
supply0 { return TOK_SUPPLY0; } supply0 { return parser::make_TOK_SUPPLY0(out_loc); }
supply1 { return TOK_SUPPLY1; } supply1 { return parser::make_TOK_SUPPLY1(out_loc); }
"$"(display[bho]?|write[bho]?|strobe|monitor|time|realtime|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) { "$"(display[bho]?|write[bho]?|strobe|monitor|time|realtime|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
yylval->string = new std::string(yytext); auto val = new std::string(YYText());
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
} }
"$"(setup|hold|setuphold|removal|recovery|recrem|skew|timeskew|fullskew|nochange) { "$"(setup|hold|setuphold|removal|recovery|recrem|skew|timeskew|fullskew|nochange) {
if (!specify_mode) REJECT; if (!specify_mode) REJECT;
yylval->string = new std::string(yytext); auto val = new std::string(YYText());
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
} }
"$"(info|warning|error|fatal) { "$"(info|warning|error|fatal) {
yylval->string = new std::string(yytext); auto val = new std::string(YYText());
return TOK_MSG_TASKS; return parser::make_TOK_MSG_TASKS(val, out_loc);
} }
"$signed" { return TOK_TO_SIGNED; } "$signed" { return parser::make_TOK_TO_SIGNED(out_loc); }
"$unsigned" { return TOK_TO_UNSIGNED; } "$unsigned" { return parser::make_TOK_TO_UNSIGNED(out_loc); }
[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* { [a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* {
// package qualifier // package qualifier
auto s = std::string("\\") + yytext; auto s = std::string("\\") + YYText();
if (pkg_user_types.count(s) > 0) { if (pkg_user_types.count(s) > 0) {
// package qualified typedefed name // package qualified typedefed name
yylval->string = new std::string(s); auto val = new std::string(s);
return TOK_PKG_USER_TYPE; return parser::make_TOK_PKG_USER_TYPE(val, out_loc);
} }
else { else {
// backup before :: just return first part // backup before :: just return first part
size_t len = strchr(yytext, ':') - yytext; size_t len = strchr(YYText(), ':') - YYText();
yyless(len); yyless(len);
yylval->string = new std::string(std::string("\\") + yytext); auto val = new std::string(std::string("\\") + YYText());
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
} }
} }
[a-zA-Z_$][a-zA-Z0-9_$]* { [a-zA-Z_$][a-zA-Z0-9_$]* {
auto s = std::string("\\") + yytext; auto s = std::string("\\") + YYText();
if (isUserType(s)) { if (isUserType(s)) {
// previously typedefed name // previously typedefed name
yylval->string = new std::string(s); auto val = new std::string(s);
return TOK_USER_TYPE; return parser::make_TOK_USER_TYPE(val, out_loc);
} }
else { else {
yylval->string = new std::string(std::string("\\") + yytext); auto val = new std::string(std::string("\\") + YYText());
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
} }
} }
[a-zA-Z_$][a-zA-Z0-9_$\.]* { [a-zA-Z_$][a-zA-Z0-9_$\.]* {
yylval->string = new std::string(std::string("\\") + yytext); auto val = new std::string(std::string("\\") + YYText());
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
} }
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" { "/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
@ -473,7 +511,7 @@ supply1 { return TOK_SUPPLY1; }
); );
printed_warning = true; printed_warning = true;
} }
return TOK_SYNOPSYS_FULL_CASE; return parser::make_TOK_SYNOPSYS_FULL_CASE(out_loc);
} }
<SYNOPSYS_FLAGS>parallel_case { <SYNOPSYS_FLAGS>parallel_case {
static bool printed_warning = false; static bool printed_warning = false;
@ -487,119 +525,115 @@ supply1 { return TOK_SUPPLY1; }
); );
printed_warning = true; printed_warning = true;
} }
return TOK_SYNOPSYS_PARALLEL_CASE; return parser::make_TOK_SYNOPSYS_PARALLEL_CASE(out_loc);
} }
<SYNOPSYS_FLAGS>. /* ignore everything else */ <SYNOPSYS_FLAGS>. /* ignore everything else */
<SYNOPSYS_FLAGS>"*/" { BEGIN(0); } <SYNOPSYS_FLAGS>"*/" { BEGIN(0); }
import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ { import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
BEGIN(IMPORT_DPI); BEGIN(IMPORT_DPI);
return TOK_DPI_FUNCTION; return parser::make_TOK_DPI_FUNCTION(out_loc);
} }
<IMPORT_DPI>[a-zA-Z_$][a-zA-Z0-9_$]* { <IMPORT_DPI>[a-zA-Z_$][a-zA-Z0-9_$]* {
yylval->string = new std::string(std::string("\\") + yytext); auto val = new std::string(std::string("\\") + YYText());
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
} }
<IMPORT_DPI>[ \t\r\n] /* ignore whitespaces */ <IMPORT_DPI>[ \t\r\n] /* ignore whitespaces */
<IMPORT_DPI>";" { <IMPORT_DPI>";" {
BEGIN(0); BEGIN(0);
return *yytext; return char_tok(*YYText(), out_loc);
} }
<IMPORT_DPI>. { <IMPORT_DPI>. {
return *yytext; return char_tok(*YYText(), out_loc);
} }
"\\"[^ \t\r\n]+ { "\\"[^ \t\r\n]+ {
yylval->string = new std::string(yytext); auto val = new std::string(YYText());
return TOK_ID; return parser::make_TOK_ID(val, out_loc);
} }
"(*" { return ATTR_BEGIN; } "(*" { return parser::make_ATTR_BEGIN(out_loc); }
"*)" { return ATTR_END; } "*)" { return parser::make_ATTR_END(out_loc); }
"{*" { return DEFATTR_BEGIN; } "{*" { return parser::make_DEFATTR_BEGIN(out_loc); }
"*}" { return DEFATTR_END; } "*}" { return parser::make_DEFATTR_END(out_loc); }
"**" { return OP_POW; } "**" { return parser::make_OP_POW(out_loc); }
"||" { return OP_LOR; } "||" { return parser::make_OP_LOR(out_loc); }
"&&" { return OP_LAND; } "&&" { return parser::make_OP_LAND(out_loc); }
"==" { return OP_EQ; } "==" { return parser::make_OP_EQ(out_loc); }
"!=" { return OP_NE; } "!=" { return parser::make_OP_NE(out_loc); }
"<=" { return OP_LE; } "<=" { return parser::make_OP_LE(out_loc); }
">=" { return OP_GE; } ">=" { return parser::make_OP_GE(out_loc); }
"===" { return OP_EQX; } "===" { return parser::make_OP_EQX(out_loc); }
"!==" { return OP_NEX; } "!==" { return parser::make_OP_NEX(out_loc); }
"~&" { return OP_NAND; } "~&" { return parser::make_OP_NAND(out_loc); }
"~|" { return OP_NOR; } "~|" { return parser::make_OP_NOR(out_loc); }
"~^" { return OP_XNOR; } "~^" { return parser::make_OP_XNOR(out_loc); }
"^~" { return OP_XNOR; } "^~" { return parser::make_OP_XNOR(out_loc); }
"<<" { return OP_SHL; } "<<" { return parser::make_OP_SHL(out_loc); }
">>" { return OP_SHR; } ">>" { return parser::make_OP_SHR(out_loc); }
"<<<" { return OP_SSHL; } "<<<" { return parser::make_OP_SSHL(out_loc); }
">>>" { return OP_SSHR; } ">>>" { return parser::make_OP_SSHR(out_loc); }
"'" { return OP_CAST; } "'" { return parser::make_OP_CAST(out_loc); }
"::" { return TOK_PACKAGESEP; } "::" { return parser::make_TOK_PACKAGESEP(out_loc); }
"++" { return TOK_INCREMENT; } "++" { return parser::make_TOK_INCREMENT(out_loc); }
"--" { return TOK_DECREMENT; } "--" { return parser::make_TOK_DECREMENT(out_loc); }
"+:" { return TOK_POS_INDEXED; } "+:" { return parser::make_TOK_POS_INDEXED(out_loc); }
"-:" { return TOK_NEG_INDEXED; } "-:" { return parser::make_TOK_NEG_INDEXED(out_loc); }
".*" { return TOK_WILDCARD_CONNECT; } ".*" { return parser::make_TOK_WILDCARD_CONNECT(out_loc); }
"|=" { SV_KEYWORD(TOK_BIT_OR_ASSIGN); } "|=" { SV_KEYWORD(parser::make_TOK_BIT_OR_ASSIGN(out_loc)); }
"&=" { SV_KEYWORD(TOK_BIT_AND_ASSIGN); } "&=" { SV_KEYWORD(parser::make_TOK_BIT_AND_ASSIGN(out_loc)); }
"+=" { SV_KEYWORD(TOK_ADD_ASSIGN); } "+=" { SV_KEYWORD(parser::make_TOK_ADD_ASSIGN(out_loc)); }
"-=" { SV_KEYWORD(TOK_SUB_ASSIGN); } "-=" { SV_KEYWORD(parser::make_TOK_SUB_ASSIGN(out_loc)); }
"^=" { SV_KEYWORD(TOK_BIT_XOR_ASSIGN); } "^=" { SV_KEYWORD(parser::make_TOK_BIT_XOR_ASSIGN(out_loc)); }
"/=" { SV_KEYWORD(TOK_DIV_ASSIGN); } "/=" { SV_KEYWORD(parser::make_TOK_DIV_ASSIGN(out_loc)); }
"%=" { SV_KEYWORD(TOK_MOD_ASSIGN); } "%=" { SV_KEYWORD(parser::make_TOK_MOD_ASSIGN(out_loc)); }
"*=" { SV_KEYWORD(TOK_MUL_ASSIGN); } "*=" { SV_KEYWORD(parser::make_TOK_MUL_ASSIGN(out_loc)); }
"<<=" { SV_KEYWORD(TOK_SHL_ASSIGN); } "<<=" { SV_KEYWORD(parser::make_TOK_SHL_ASSIGN(out_loc)); }
">>=" { SV_KEYWORD(TOK_SHR_ASSIGN); } ">>=" { SV_KEYWORD(parser::make_TOK_SHR_ASSIGN(out_loc)); }
"<<<=" { SV_KEYWORD(TOK_SSHL_ASSIGN); } "<<<=" { SV_KEYWORD(parser::make_TOK_SSHL_ASSIGN(out_loc)); }
">>>=" { SV_KEYWORD(TOK_SSHR_ASSIGN); } ">>>=" { SV_KEYWORD(parser::make_TOK_SSHR_ASSIGN(out_loc)); }
[-+]?[=*]> { [-+]?[=*]> {
if (!specify_mode) REJECT; if (!specify_mode) REJECT;
yylval->string = new std::string(yytext); auto val = new std::string(YYText());
return TOK_SPECIFY_OPER; return parser::make_TOK_SPECIFY_OPER(val, out_loc);
} }
"&&&" { "&&&" {
if (!specify_mode) return TOK_IGNORED_SPECIFY_AND; if (!specify_mode) return parser::make_TOK_IGNORED_SPECIFY_AND(out_loc);
return TOK_SPECIFY_AND; return parser::make_TOK_SPECIFY_AND(out_loc);
} }
{UNSIGNED_NUMBER}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; } {UNSIGNED_NUMBER}{TIME_SCALE_SUFFIX} { return parser::make_TOK_TIME_SCALE(out_loc); }
{FIXED_POINT_NUMBER_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; } {FIXED_POINT_NUMBER_DEC}{TIME_SCALE_SUFFIX} { return parser::make_TOK_TIME_SCALE(out_loc); }
{FIXED_POINT_NUMBER_NO_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; } {FIXED_POINT_NUMBER_NO_DEC}{TIME_SCALE_SUFFIX} { return parser::make_TOK_TIME_SCALE(out_loc); }
<INITIAL,BASED_CONST>"/*" { comment_caller=YY_START; BEGIN(COMMENT); } <INITIAL,BASED_CONST>"/*" { comment_caller=YY_START; BEGIN(COMMENT); }
<COMMENT>. /* ignore comment body */ <COMMENT>. /* ignore comment body */
<COMMENT>\n /* ignore comment body */ <COMMENT>\n /* ignore comment body */
<COMMENT>"*/" { BEGIN(comment_caller); } <COMMENT>"*/" { BEGIN(comment_caller); }
<INITIAL,BASED_CONST>[ \t\r\n] /* ignore whitespaces */ <INITIAL,BASED_CONST>[ \t\r\n] /* ignore whitespaces */
<INITIAL,BASED_CONST>\\[\r\n] /* ignore continuation sequence */ <INITIAL,BASED_CONST>\\[\r\n] /* ignore continuation sequence */
<INITIAL,BASED_CONST>"//"[^\r\n]* /* ignore one-line comments */ <INITIAL,BASED_CONST>"//"[^\r\n]* /* ignore one-line comments */
<INITIAL>. { return *yytext; } <INITIAL>. { return char_tok(*YYText(), out_loc); }
<*>. { BEGIN(0); return *yytext; } <*>. { BEGIN(0); return char_tok(*YYText(), out_loc); }
%% %%
// this is a hack to avoid the 'yyinput defined but not used' error msgs
void *frontend_verilog_avoid_input_warnings() {
return (void*)&yyinput;
}

File diff suppressed because it is too large Load diff

View file

@ -947,10 +947,6 @@ RTLIL::Design::~Design()
delete pr.second; delete pr.second;
for (auto n : bindings_) for (auto n : bindings_)
delete n; delete n;
for (auto n : verilog_packages)
delete n;
for (auto n : verilog_globals)
delete n;
#ifdef WITH_PYTHON #ifdef WITH_PYTHON
RTLIL::Design::get_all_designs()->erase(hashidx_); RTLIL::Design::get_all_designs()->erase(hashidx_);
#endif #endif
@ -5708,12 +5704,12 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri
if (('0' <= netname[0] && netname[0] <= '9') || netname[0] == '\'') { if (('0' <= netname[0] && netname[0] <= '9') || netname[0] == '\'') {
cover("kernel.rtlil.sigspec.parse.const"); cover("kernel.rtlil.sigspec.parse.const");
AST::get_line_num = sigspec_parse_get_dummy_line_num; // TODO fix
AST::AstNode *ast = VERILOG_FRONTEND::const2ast(netname); // AST::get_line_num = sigspec_parse_get_dummy_line_num;
if (ast == NULL) auto ast = VERILOG_FRONTEND::const2ast(netname);
if (ast == nullptr)
return false; return false;
sig.append(RTLIL::Const(ast->bits)); sig.append(RTLIL::Const(ast->bits));
delete ast;
continue; continue;
} }

View file

@ -1331,7 +1331,7 @@ struct RTLIL::Design
dict<RTLIL::IdString, RTLIL::Module*> modules_; dict<RTLIL::IdString, RTLIL::Module*> modules_;
std::vector<RTLIL::Binding*> bindings_; std::vector<RTLIL::Binding*> bindings_;
std::vector<AST::AstNode*> verilog_packages, verilog_globals; std::vector<std::unique_ptr<AST::AstNode>> verilog_packages, verilog_globals;
std::unique_ptr<define_map_t> verilog_defines; std::unique_ptr<define_map_t> verilog_defines;
std::vector<RTLIL::Selection> selection_stack; std::vector<RTLIL::Selection> selection_stack;

View file

@ -368,14 +368,8 @@ struct DesignPass : public Pass {
if (reset_mode || reset_vlog_mode || !load_name.empty() || push_mode || pop_mode) if (reset_mode || reset_vlog_mode || !load_name.empty() || push_mode || pop_mode)
{ {
for (auto node : design->verilog_packages)
delete node;
design->verilog_packages.clear(); design->verilog_packages.clear();
for (auto node : design->verilog_globals)
delete node;
design->verilog_globals.clear(); design->verilog_globals.clear();
design->verilog_defines->clear(); design->verilog_defines->clear();
} }

View file

@ -100,7 +100,7 @@ enum class WrTransKind {
struct WrTransDef { struct WrTransDef {
WrTransTargetKind target_kind; WrTransTargetKind target_kind;
int target_group; int target_group = 0;
WrTransKind kind; WrTransKind kind;
}; };

View file

@ -1,4 +1,4 @@
module alu( module alu (
input clk, input clk,
input [7:0] A, input [7:0] A,
input [7:0] B, input [7:0] B,

View file

@ -27,7 +27,7 @@ always_comb @(d)
endmodule endmodule
EOT EOT
) 2>&1 | grep -F "<stdin>:3: ERROR: syntax error, unexpected '@'" > /dev/null ) 2>&1 | grep -F "ERROR: syntax error, unexpected @" > /dev/null
# Incorrect use of always_comb # Incorrect use of always_comb
((../../yosys -f "verilog -sv" -qp proc -|| true) <<EOT ((../../yosys -f "verilog -sv" -qp proc -|| true) <<EOT

View file

@ -48,7 +48,7 @@ sat -verify -prove-asserts
design -reset design -reset
logger -expect error "syntax error, unexpected TOK_ENDTASK, expecting ';'" 1 logger -expect error "syntax error, unexpected TOK_ENDTASK, expecting ;" 1
read_verilog -sv <<EOT read_verilog -sv <<EOT
module Task_Test_Top module Task_Test_Top
( (

View file

@ -15,7 +15,7 @@ EOT
select -assert-none a:* a:src %d select -assert-none a:* a:src %d
logger -expect error "syntax error, unexpected ';', expecting ATTR_BEGIN or TOK_INCREMENT or TOK_DECREMENT" 1 logger -expect error "syntax error, unexpected ;, expecting ATTR_BEGIN or TOK_INCREMENT or TOK_DECREMENT" 1
design -reset design -reset
read_verilog <<EOT read_verilog <<EOT
module top; module top;