3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-06-20 04:43:40 +00:00

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

This commit is contained in:
Emil J. Tywoniak 2025-06-16 22:55:24 +02:00
parent cd71f190cd
commit 8a9f491ffc
19 changed files with 3295 additions and 3312 deletions

View file

@ -39,8 +39,7 @@ using namespace AST_INTERNAL;
// instantiate global variables (public API)
namespace AST {
std::string current_filename;
void (*set_line_num)(int) = NULL;
int (*get_line_num)() = NULL;
bool sv_mode;
unsigned long long astnodes = 0;
unsigned long long astnode_count() { return astnodes; }
}
@ -192,16 +191,16 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
if (attributes.count(id) == 0)
return false;
AstNode *attr = attributes.at(id);
if (attr->type != AST_CONSTANT)
attr->input_error("Attribute `%s' with non-constant value!\n", id.c_str());
AstNode& attr = *(attributes.at(id));
if (attr.type != AST_CONSTANT)
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)
// (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;
hashidx_count = mkhash_xorshift(hashidx_count);
@ -239,56 +238,74 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
in_param = false;
if (child1)
children.push_back(child1);
children.push_back(std::move(child1));
if (child2)
children.push_back(child2);
children.push_back(std::move(child2));
if (child3)
children.push_back(child3);
children.push_back(std::move(child3));
if (child4)
children.push_back(child4);
children.push_back(std::move(child4));
fixup_hierarchy_flags();
}
// create a (deep recursive) copy of a node
AstNode *AstNode::clone() const
std::unique_ptr<AstNode> AstNode::clone() const
{
AstNode *that = new AstNode;
*that = *this;
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
auto that = std::make_unique<AstNode>(this->type);
cloneInto(*that.get());
return that;
}
// 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();
tmp->in_lvalue_from_above = other->in_lvalue_from_above;
tmp->in_param_from_above = other->in_param_from_above;
other->delete_children();
*other = *tmp;
tmp->children.clear();
tmp->attributes.clear();
other->fixup_hierarchy_flags();
delete tmp;
other.type = type;
other.str = str;
other.bits = bits;
other.is_input = is_input;
other.is_output = is_output;
other.is_reg = is_reg;
other.is_logic = is_logic;
other.is_signed = is_signed;
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
void AstNode::delete_children()
{
for (auto &it : children)
delete it;
children.clear();
for (auto &it : attributes)
delete it.second;
attributes.clear();
}
@ -423,18 +440,18 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
{
case AST_MODULE:
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)) {
fprintf(f, "%s%s", first ? "" : ", ", id2vl(child->str).c_str());
first = false;
}
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)
child->dumpVlog(f, indent + " ");
else
rem_children1.push_back(child);
rem_children1.push_back(child.get());
for (auto child : rem_children1)
if (child->type == AST_WIRE || child->type == AST_AUTOWIRE || child->type == AST_MEMORY)
@ -470,7 +487,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "%s" "reg", (is_input || is_output) ? " " : indent.c_str());
if (is_signed)
fprintf(f, " signed");
for (auto child : children) {
for (const auto& child : children) {
fprintf(f, " ");
child->dumpVlog(f, "");
}
@ -486,7 +503,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "%s" "memory", indent.c_str());
if (is_signed)
fprintf(f, " signed");
for (auto child : children) {
for (const auto& child : children) {
fprintf(f, " ");
child->dumpVlog(f, "");
if (first)
@ -500,7 +517,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
if (0) { case AST_MEMINIT: txt = "@meminit@"; }
if (0) { case AST_MEMWR: txt = "@memwr@"; }
fprintf(f, "%s%s", indent.c_str(), txt.c_str());
for (auto child : children) {
for (const auto& child : children) {
fprintf(f, first ? "(" : ", ");
child->dumpVlog(f, "");
first = false;
@ -517,7 +534,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
else
fprintf(f, "[%d:%d]", range_left, range_right);
} else {
for (auto child : children) {
for (const auto& child : children) {
fprintf(f, "%c", first ? '[' : ':');
child->dumpVlog(f, "");
first = false;
@ -527,13 +544,13 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
break;
case AST_MULTIRANGE:
for (auto child : children)
for (const auto& child : children)
child->dumpVlog(f, "");
break;
case AST_ALWAYS:
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)
continue;
fprintf(f, first ? "(" : ", ");
@ -541,7 +558,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
first = false;
}
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)
child->dumpVlog(f, indent + " ");
}
@ -549,7 +566,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_INITIAL:
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)
child->dumpVlog(f, indent + " ");
}
@ -562,7 +579,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "posedge ");
if (type == AST_NEGEDGE)
fprintf(f, "negedge ");
for (auto child : children)
for (const auto& child : children)
child->dumpVlog(f, "");
break;
@ -574,7 +591,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
else
fprintf(f, "%s", id2vl(str).c_str());
}
for (auto child : children)
for (const auto& child : children)
child->dumpVlog(f, "");
break;
@ -602,7 +619,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
children[0]->dumpVlog(f, indent);
} else {
fprintf(f, "%s" "begin\n", indent.c_str());
for (auto child : children)
for (const auto& child : children)
child->dumpVlog(f, indent + " ");
fprintf(f, "%s" "end\n", indent.c_str());
}
@ -618,7 +635,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
children[0]->dumpVlog(f, "");
fprintf(f, ")\n");
for (size_t i = 1; i < children.size(); i++) {
AstNode *child = children[i];
const auto& child = children[i];
child->dumpVlog(f, indent + " ");
}
fprintf(f, "%s" "endcase\n", indent.c_str());
@ -627,7 +644,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_COND:
case AST_CONDX:
case AST_CONDZ:
for (auto child : children) {
for (const auto& child : children) {
if (child->type == AST_BLOCK) {
fprintf(f, ":\n");
child->dumpVlog(f, indent + " ");
@ -663,7 +680,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_CONCAT:
fprintf(f, "{");
for (int i = GetSize(children)-1; i >= 0; i--) {
auto child = children[i];
const auto& child = children[i];
if (!first)
fprintf(f, ", ");
child->dumpVlog(f, "");
@ -818,16 +835,16 @@ bool AstNode::contains(const AstNode *other) const
{
if (this == other)
return true;
for (auto child : children)
for (const auto& child : children)
if (child->contains(other))
return true;
return false;
}
// 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->is_signed = is_signed;
for (int i = 0; i < width; i++) {
@ -841,9 +858,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)
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->bits = v;
for (size_t i = 0; i < 32; i++) {
@ -859,15 +876,15 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
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);
}
// 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))
node->bits.push_back(RTLIL::State::S0);
log_assert(node->bits == v);
@ -875,9 +892,9 @@ AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
}
// 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
// equivalent to the ASCII NUL ("\0")
@ -902,18 +919,19 @@ AstNode *AstNode::mkconst_str(const std::string &str)
}
// 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++);
if (nosync)
wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
wire->is_signed = is_signed;
wire->is_logic = true;
mod->children.push_back(wire);
mod->children.push_back(std::move(wire_owned));
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->id2ast = wire;
@ -967,10 +985,9 @@ RTLIL::Const AstNode::asParaConst() const
{
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();
val.flags |= RTLIL::CONST_FLAG_REAL;
delete strnode;
return val;
}
@ -1078,7 +1095,7 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
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;
log_assert(param->type == AST_PARAMETER);
log_assert(children.size() <= 2);
@ -1086,7 +1103,7 @@ static bool param_has_no_default(const AstNode *param) {
(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(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
@ -1100,15 +1117,15 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
AstModule *module = new AstModule;
current_module = module;
module->ast = NULL;
module->ast = nullptr;
module->name = ast->str;
set_src_attr(module, ast);
module->set_bool_attribute(ID::cells_not_processed);
current_ast_mod = ast;
AstNode *ast_before_simplify;
std::unique_ptr<AstNode> ast_before_simplify;
if (original_ast != NULL)
ast_before_simplify = original_ast;
ast_before_simplify = std::move(original_ast);
else
ast_before_simplify = ast->clone();
@ -1125,7 +1142,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (!defer)
{
for (const AstNode *node : ast->children)
for (auto& node : ast->children)
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());
@ -1133,7 +1150,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (!blackbox_module && !flag_noblackbox) {
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))
continue;
if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
@ -1163,36 +1180,33 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
ast->dumpVlog(NULL, " ");
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)) {
delete ast->attributes.at(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 (!flag_lib || flag_nowb) {
delete ast->attributes.at(ID::lib_whitebox);
ast->attributes.erase(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);
if (flag_lib && !flag_nowb) {
ast->attributes[ID::whitebox] = std::move(
ast->attributes[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)) {
AstNode *n = ast->attributes.at(ID::blackbox);
auto& n = ast->attributes.at(ID::blackbox);
if (n->type != AST_CONSTANT)
ast->input_error("Got blackbox attribute with non-constant value!\n");
blackbox_module = n->asBool();
}
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)
ast->input_error("Got whitebox attribute with non-constant value!\n");
blackbox_module = !n->asBool();
@ -1200,38 +1214,34 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (ast->attributes.count(ID::noblackbox)) {
if (blackbox_module) {
AstNode *n = ast->attributes.at(ID::noblackbox);
auto& n = ast->attributes.at(ID::noblackbox);
if (n->type != AST_CONSTANT)
ast->input_error("Got noblackbox attribute with non-constant value!\n");
blackbox_module = !n->asBool();
}
delete ast->attributes.at(ID::noblackbox);
ast->attributes.erase(ID::noblackbox);
}
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (blackbox_module)
{
if (ast->attributes.count(ID::whitebox)) {
delete ast->attributes.at(ID::whitebox);
ast->attributes.erase(ID::whitebox);
}
if (ast->attributes.count(ID::lib_whitebox)) {
delete ast->attributes.at(ID::lib_whitebox);
ast->attributes.erase(ID::lib_whitebox);
}
std::vector<AstNode*> new_children;
for (auto child : ast->children) {
std::vector<std::unique_ptr<AstNode>> new_children;
for (auto& child : ast->children) {
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) {
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 &&
(child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) {
new_children.push_back(child);
} else {
delete child;
new_children.push_back(std::move(child));
}
}
@ -1245,17 +1255,18 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
ignoreThisSignalsInInitial = RTLIL::SigSpec();
for (auto &attr : ast->attributes) {
log_assert((bool)attr.second.get());
if (attr.second->type != AST_CONSTANT)
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
module->attributes[attr.first] = attr.second->asAttrConst();
}
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->genRTLIL();
}
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)
node->genRTLIL();
}
@ -1263,7 +1274,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
ignoreThisSignalsInInitial.sort_and_unify();
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)
node->genRTLIL();
}
@ -1277,14 +1288,14 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
continue;
module->attributes[attr.first] = attr.second->asAttrConst();
}
for (const AstNode *node : ast->children)
for (const auto& node : ast->children)
if (node->type == AST_PARAMETER)
current_module->avail_parameters(node->str);
}
if (ast->type == AST_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->nomeminit = flag_nomeminit;
module->nomem2reg = flag_nomem2reg;
@ -1311,8 +1322,8 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
RTLIL::Module *
AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
RTLIL::Module *old_module,
AstNode *new_ast,
AstNode *original_ast)
AST::AstNode *new_ast,
std::unique_ptr<AstNode> original_ast)
{
// The old module will be deleted. Rename and mark for deletion, using
// a static counter to make sure we get a unique name.
@ -1335,7 +1346,7 @@ AST_INTERNAL::process_and_replace_module(RTLIL::Design *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)
new_module->set_bool_attribute(ID::top);
@ -1347,17 +1358,17 @@ AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
static void rename_in_package_stmts(AstNode *pkg)
{
std::unordered_set<std::string> idents;
for (AstNode *item : pkg->children)
for (auto& item : pkg->children)
idents.insert(item->str);
std::function<void(AstNode*)> rename =
[&rename, &idents, pkg](AstNode *node) {
for (AstNode *child : node->children) {
std::function<void(std::unique_ptr<AstNode>&)> rename =
[&rename, &idents, pkg](std::unique_ptr<AstNode>& node) {
for (auto& child : node->children) {
if (idents.count(child->str))
child->str = pkg->str + "::" + child->str.substr(1);
rename(child);
}
};
for (AstNode *item : pkg->children)
for (auto& item : pkg->children)
if (item->type == AST_FUNCTION || item->type == AST_TASK)
rename(item);
}
@ -1390,17 +1401,17 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
ast->fixup_hierarchy_flags(true);
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)
{
for (auto n : design->verilog_globals)
for (auto& n : design->verilog_globals)
child->children.push_back(n->clone());
// 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) {
AstNode *cloned_node = o->clone();
auto cloned_node = o->clone();
// log("cloned node %s\n", type2str(cloned_node->type).c_str());
if (cloned_node->type == AST_ENUM) {
for (auto &e : cloned_node->children) {
@ -1410,7 +1421,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
} else {
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 +1430,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
bool defer_local = defer;
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))
{
log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str.c_str());
@ -1447,13 +1458,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;
}
else if (child->type == AST_PACKAGE) {
// process enum/other declarations
child->simplify(true, 1, -1, false);
rename_in_package_stmts(child);
rename_in_package_stmts(child.get());
design->verilog_packages.push_back(child->clone());
current_scope.clear();
}
@ -1470,16 +1481,9 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
current_scope.clear();
}
}
}
// AstModule destructor
AstModule::~AstModule()
{
if (ast != NULL)
delete ast;
}
// An interface port with modport is specified like this:
// <interface_name>.<modport_name>
// This function splits the interface_name from the modport_name, and fails if it is not a valid combination
@ -1516,7 +1520,7 @@ AstNode * AST::find_modport(AstNode *intf, std::string name)
for (auto &ch : intf->children)
if (ch->type == AST_MODPORT)
if (ch->str == name) // Modport found
return ch;
return ch.get();
return NULL;
}
@ -1524,7 +1528,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)
{
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 newname = intfname + "." + origname;
wire->str = newname;
@ -1543,16 +1547,13 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule
}
}
if (found_in_modport) {
module_ast->children.push_back(wire);
}
else { // If not found in modport, do not create port
delete wire;
module_ast->children.push_back(std::move(wire));
}
}
else { // If no modport, set inout
wire->is_input = true;
wire->is_output = true;
module_ast->children.push_back(wire);
module_ast->children.push_back(std::move(wire));
}
}
}
@ -1570,7 +1571,7 @@ bool AstModule::reprocess_if_necessary(RTLIL::Design *design)
log("Reprocessing module %s because instantiated module %s has become available.\n",
log_id(name), log_id(modname));
loadconfig();
process_and_replace_module(design, this, ast, NULL);
process_and_replace_module(design, this, ast.get(), NULL);
return true;
}
}
@ -1583,32 +1584,32 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
{
loadconfig();
AstNode *new_ast = ast->clone();
auto new_ast = ast->clone();
for (auto &intf : local_interfaces) {
std::string intfname = intf.first.str();
RTLIL::Module *intfmodule = intf.second;
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);
newname = intfname + "." + 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
// level' modules. Other sub-modules will have their interface ports
// exploded via the derive(..) function
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
std::string name_port = ch2->str; // Name of the interface port
if (ch2->children.size() > 0) {
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
std::pair<std::string,std::string> res = split_modport_from_type(ch->str);
std::string interface_type = res.first;
@ -1616,11 +1617,11 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
if (design->module(interface_type) != nullptr) {
// Add a cell to the module corresponding to the interface port such that
// 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;
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";
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:
RTLIL::Module *intfmodule = design->module(interface_type); // All interfaces should at this point in time (assuming
@ -1628,9 +1629,9 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
// present in design->modules_
AstModule *ast_module_of_interface = (AstModule*)intfmodule;
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:
explode_interface_port(new_ast, intfmodule, name_port, modport);
explode_interface_port(new_ast.get(), intfmodule, name_port, modport);
}
break;
}
@ -1642,9 +1643,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,
// renaming this module to move it out of the way.
RTLIL::Module* new_module =
process_and_replace_module(design, this, new_ast, ast_before_replacing_interface_ports);
delete new_ast;
process_and_replace_module(design, this, new_ast.get(), std::move(ast_before_replacing_interface_ports));
// Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
new_module->set_bool_attribute(ID::interfaces_replaced_in_module);
@ -1654,7 +1653,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)
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);
// Since interfaces themselves may be instantiated with different parameters,
@ -1690,14 +1689,14 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
if (modports.count(intfname) > 0) {
std::string interface_modport = modports.at(intfname).str();
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);
}
// 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();
RTLIL::Module* mod = design->module(modname);
@ -1734,7 +1733,6 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
}
delete new_ast;
return modname;
}
@ -1743,18 +1741,17 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
{
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);
if (!design->has(modname) && new_ast) {
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();
} else if (!quiet) {
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
}
delete new_ast;
return modname;
}
@ -1784,7 +1781,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
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();
(*new_ast_out) = nullptr;
@ -1794,7 +1791,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
int para_counter = 0;
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)
continue;
para_counter++;
@ -1828,12 +1825,12 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
pool<IdString> rewritten;
rewritten.reserve(GetSize(parameters));
AstNode *new_ast = ast->clone();
auto new_ast = ast->clone();
if (!new_ast->attributes.count(ID::hdlname))
new_ast->set_attribute(ID::hdlname, AstNode::mkconst_str(stripped_name.substr(1)));
para_counter = 0;
for (auto child : new_ast->children) {
for (auto& child : new_ast->children) {
if (child->type != AST_PARAMETER)
continue;
para_counter++;
@ -1853,9 +1850,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
rewrite_parameter:
if (param_has_no_default(child))
child->children.insert(child->children.begin(), nullptr);
delete child->children.at(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());
} else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0)
child->children[0] = AstNode::mkconst_str(it->second.decode_string());
@ -1868,17 +1864,17 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
for (const auto &param : parameters) {
if (rewritten.count(param.first))
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();
if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0)
defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string()));
else
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_out) = new_ast;
new_ast_out->reset(new_ast.release());
return modname;
}

View file

@ -183,10 +183,10 @@ namespace AST
AstNodeType type;
// 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
std::map<RTLIL::IdString, AstNode*> attributes;
std::map<RTLIL::IdString, std::unique_ptr<AstNode>> attributes;
bool get_bool_attribute(RTLIL::IdString id);
// node content - most of it is unused in most node types
@ -212,7 +212,7 @@ namespace AST
int unpacked_dimensions;
// 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
bool basic_prep;
@ -234,9 +234,9 @@ namespace AST
bool in_param_from_above;
// creating and deleting nodes
AstNode(AstNodeType type = AST_NONE, AstNode *child1 = nullptr, AstNode *child2 = nullptr, AstNode *child3 = nullptr, AstNode *child4 = nullptr);
AstNode *clone() const;
void cloneInto(AstNode *other) const;
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);
std::unique_ptr<AstNode> clone() const;
void cloneInto(AstNode &other) const;
void delete_children();
~AstNode();
@ -264,15 +264,16 @@ namespace AST
// 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()
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);
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 label_genblks(std::set<std::string>& existing, int &counter);
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);
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);
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);
bool detect_latch(const std::string &var);
const RTLIL::Module* lookup_cell_module();
@ -288,7 +289,7 @@ namespace AST
};
bool has_const_only_constructs();
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();
// helper for parsing format strings
@ -305,29 +306,30 @@ namespace AST
std::vector<RTLIL::Binding *> genBindings() const;
// used by genRTLIL() for detecting expression width and sign
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = NULL);
void detectSignWidth(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 = nullptr);
// create RTLIL code for this AST node
// 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
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
bool operator==(const AstNode &other) const;
bool operator!=(const AstNode &other) const;
bool contains(const AstNode *other) const;
AstNode operator=(AstNode) = delete;
// helper functions for creating AST nodes for constants
static 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 AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
static AstNode *mkconst_str(const std::string &str);
static std::unique_ptr<AstNode> mkconst_int(uint32_t v, bool is_signed, int width = 32);
static std::unique_ptr<AstNode> mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
static std::unique_ptr<AstNode> mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
static std::unique_ptr<AstNode> mkconst_str(const std::vector<RTLIL::State> &v);
static std::unique_ptr<AstNode> mkconst_str(const std::string &str);
// 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
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
// 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);
attributes[key] = std::move(node);
}
// 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);
// 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;
// helper to print errors from simplify/genrtlil code
@ -391,12 +393,11 @@ namespace AST
// parametric modules are supported directly by the AST library
// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
struct AstModule : RTLIL::Module {
AstNode *ast;
std::unique_ptr<AstNode> ast;
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, 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;
bool reprocess_if_necessary(RTLIL::Design *design) override;
RTLIL::Module *clone() const override;
@ -407,8 +408,8 @@ namespace AST
// the AstNode constructor then uses current_filename and get_line_num()
// to initialize the filename and linenum properties of new nodes
extern std::string current_filename;
extern void (*set_line_num)(int);
extern int (*get_line_num)();
// also set by the language frontend to control some AST processing
extern bool sv_mode;
// for stats
unsigned long long astnode_count();
@ -418,7 +419,7 @@ namespace AST
void use_internal_line_num();
// 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
std::pair<std::string,std::string> split_modport_from_type(std::string name_type);
@ -464,7 +465,7 @@ namespace AST_INTERNAL
process_and_replace_module(RTLIL::Design *design,
RTLIL::Module *old_module,
AST::AstNode *new_ast,
AST::AstNode *original_ast = nullptr);
std::unique_ptr<AST::AstNode> original_ast = nullptr);
}
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());
}
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; };
std::vector<value> value_store(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());
if (rtype == "real") {
newNode = new AstNode(AST_REALVALUE);
newNode = std::make_unique<AstNode>(AST_REALVALUE);
newNode->realvalue = value_store[args.size()].f64;
log(" return realvalue: %g\n", newNode->asReal(true));
} else if (rtype == "shortreal") {
newNode = new AstNode(AST_REALVALUE);
newNode = std::make_unique<AstNode>(AST_REALVALUE);
newNode->realvalue = value_store[args.size()].f32;
log(" return realvalue: %g\n", newNode->asReal(true));
} 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);
wire->is_signed = that->is_signed;
if (that != NULL)
if (that != nullptr)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
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) {
log_assert(node->type == AST_IDENTIFIER);
if (!lookaheadids.count(node->str)) {
AstNode *wire = new AstNode(AST_WIRE);
for (auto c : node->id2ast->children)
auto wire = std::make_unique<AstNode>(AST_WIRE);
for (auto& c : node->id2ast->children)
wire->children.push_back(c->clone());
wire->fixup_hierarchy_flags();
wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++);
wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
wire->is_logic = true;
while (wire->simplify(true, 1, -1, false)) { }
current_ast_mod->children.push_back(wire);
lookaheadids[node->str] = make_pair(node->id2ast, wire);
lookaheadids[node->str] = make_pair(node->id2ast, wire.get());
wire->genRTLIL();
current_ast_mod->children.push_back(std::move(wire));
}
}
for (auto child : node->children)
collect_lookaheadids(child);
for (auto& child : node->children)
collect_lookaheadids(child.get());
}
bool has_lookaheadids(AstNode *node)
@ -218,8 +218,8 @@ struct AST_INTERNAL::LookaheadRewriter
if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0)
return true;
for (auto child : node->children)
if (has_lookaheadids(child))
for (auto& child : node->children)
if (has_lookaheadids(child.get()))
return true;
return false;
@ -230,8 +230,8 @@ struct AST_INTERNAL::LookaheadRewriter
if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0)
return true;
for (auto child : node->children)
if (has_nonlookaheadids(child))
for (auto& child : node->children)
if (has_nonlookaheadids(child.get()))
return true;
return false;
@ -241,16 +241,16 @@ struct AST_INTERNAL::LookaheadRewriter
{
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");
rewrite_lookaheadids(node->children[0], true);
rewrite_lookaheadids(node->children[0].get(), true);
node->type = AST_ASSIGN_EQ;
}
rewrite_lookaheadids(node->children[1], lhs);
rewrite_lookaheadids(node->children[1].get(), lhs);
return;
}
@ -261,21 +261,21 @@ struct AST_INTERNAL::LookaheadRewriter
lhs = false;
}
for (auto child : node->children)
rewrite_lookaheadids(child, lhs);
for (auto& child : node->children)
rewrite_lookaheadids(child.get(), lhs);
}
LookaheadRewriter(AstNode *top)
{
// top->dumpAst(NULL, "REWRITE-BEFORE> ");
// top->dumpVlog(NULL, "REWRITE-BEFORE> ");
// top->dumpAst(nullptr, "REWRITE-BEFORE> ");
// top->dumpVlog(nullptr, "REWRITE-BEFORE> ");
AstNode *block = nullptr;
for (auto c : top->children)
for (auto& c : top->children)
if (c->type == AST_BLOCK) {
log_assert(block == nullptr);
block = c;
block = c.get();
}
log_assert(block != nullptr);
@ -284,25 +284,25 @@ struct AST_INTERNAL::LookaheadRewriter
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->id2ast = it.second.first;
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->id2ast = it.second.second;
ref_temp->was_checked = true;
AstNode *init_assign = new AstNode(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone());
AstNode *final_assign = new AstNode(AST_ASSIGN_LE, ref_orig, ref_temp);
auto init_assign = std::make_unique<AstNode>(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone());
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.push_back(final_assign);
block->children.insert(block->children.begin(), std::move(init_assign));
block->children.push_back(std::move(final_assign));
}
// top->dumpAst(NULL, "REWRITE-AFTER> ");
// top->dumpVlog(NULL, "REWRITE-AFTER> ");
// top->dumpAst(nullptr, "REWRITE-AFTER> ");
// top->dumpVlog(nullptr, "REWRITE-AFTER> ");
}
};
@ -310,7 +310,7 @@ struct AST_INTERNAL::LookaheadRewriter
struct AST_INTERNAL::ProcessGenerator
{
// input and output structures
AstNode *always;
std::unique_ptr<AstNode> always;
RTLIL::SigSpec initSyncSignals;
RTLIL::Process *proc;
RTLIL::SigSpec outputSignals;
@ -341,14 +341,14 @@ struct AST_INTERNAL::ProcessGenerator
// The most recently assigned $print or $check cell \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
LookaheadRewriter la_rewriter(always);
LookaheadRewriter la_rewriter(always.get());
// 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++));
set_src_attr(proc, always);
set_src_attr(proc, always.get());
for (auto &attr : always->attributes) {
if (attr.second->type != AST_CONSTANT)
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
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_map = subst_lvalue_from.to_sigbit_map(subst_lvalue_to);
bool found_global_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 &&
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
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 (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))
@ -420,9 +420,9 @@ struct AST_INTERNAL::ProcessGenerator
}
// process the AST
for (auto child : always->children)
for (auto& child : always->children)
if (child->type == AST_BLOCK)
processAst(child);
processAst(child.get());
for (auto sync: proc->syncs)
processMemWrites(sync);
@ -472,7 +472,7 @@ struct AST_INTERNAL::ProcessGenerator
for (int i = 0; i < GetSize(chunks); i++)
{
RTLIL::SigChunk &chunk = chunks[i];
if (chunk.wire == NULL)
if (chunk.wire == nullptr)
continue;
std::string wire_name;
@ -484,7 +484,7 @@ struct AST_INTERNAL::ProcessGenerator
} while (current_module->wires_.count(wire_name) > 0);
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.offset = 0;
@ -499,10 +499,10 @@ struct AST_INTERNAL::ProcessGenerator
switch (ast->type)
{
case AST_CASE:
for (auto child : ast->children)
for (auto& child : ast->children)
if (child != ast->children[0]) {
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;
@ -511,19 +511,19 @@ struct AST_INTERNAL::ProcessGenerator
case AST_CONDZ:
case AST_ALWAYS:
case AST_INITIAL:
for (auto child : ast->children)
for (auto& child : ast->children)
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;
case AST_BLOCK:
for (auto child : ast->children) {
for (auto& child : ast->children) {
if (child->type == AST_ASSIGN_EQ && type_eq)
reg.append(child->children[0]->genRTLIL());
if (child->type == AST_ASSIGN_LE && type_le)
reg.append(child->children[0]->genRTLIL());
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;
@ -583,8 +583,8 @@ struct AST_INTERNAL::ProcessGenerator
switch (ast->type)
{
case AST_BLOCK:
for (auto child : ast->children)
processAst(child);
for (auto& child : ast->children)
processAst(child.get());
break;
case AST_ASSIGN_EQ:
@ -641,9 +641,9 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::SigSpec this_case_eq_rvalue = this_case_eq_lvalue;
this_case_eq_rvalue.replace(subst_rvalue_map.stdmap());
RTLIL::CaseRule *default_case = NULL;
RTLIL::CaseRule *last_generated_case = NULL;
for (auto child : ast->children)
RTLIL::CaseRule *default_case = nullptr;
RTLIL::CaseRule *last_generated_case = nullptr;
for (auto& child : ast->children)
{
if (child == ast->children[0])
continue;
@ -657,14 +657,14 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::CaseRule *backup_case = current_case;
current_case = new RTLIL::CaseRule;
set_src_attr(current_case, child);
set_src_attr(current_case, child.get());
last_generated_case = current_case;
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)
default_case = current_case;
else if (node->type == AST_BLOCK)
processAst(node);
processAst(node.get());
else
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();
}
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
// this is a valid transformation, but as optimization it is premature.
// 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);
#endif
} else {
if (default_case == NULL) {
if (default_case == nullptr) {
default_case = new RTLIL::CaseRule;
addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
}
@ -760,7 +760,7 @@ struct AST_INTERNAL::ProcessGenerator
default_base = 16;
std::vector<VerilogFmtArg> args;
for (auto node : ast->children) {
for (auto& node : ast->children) {
int width;
bool is_signed;
node->detectSignWidth(width, is_signed, nullptr);
@ -866,8 +866,8 @@ struct AST_INTERNAL::ProcessGenerator
break;
default:
// ast->dumpAst(NULL, "ast> ");
// current_ast_mod->dumpAst(NULL, "mod> ");
// ast->dumpAst(nullptr, "ast> ");
// current_ast_mod->dumpAst(nullptr, "mod> ");
log_abort();
}
}
@ -876,14 +876,14 @@ struct AST_INTERNAL::ProcessGenerator
{
// Maps per-memid AST_MEMWR IDs to indices in the mem_write_actions array.
dict<std::pair<std::string, int>, int> port_map;
for (auto child : always->children)
for (auto& child : always->children)
if (child->type == AST_MEMWR)
{
std::string memid = child->str;
int portid = child->children[3]->asInt(false);
int cur_idx = GetSize(sync->mem_write_actions);
RTLIL::MemWriteAction action;
set_src_attr(&action, child);
set_src_attr(&action, child.get());
action.memid = memid;
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());
@ -971,11 +971,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
bool sub_sign_hint = true;
int sub_width_hint = -1;
int this_width = 0;
AstNode *range = NULL;
AstNode *id_ast = NULL;
AstNode *range = nullptr;
AstNode *id_ast = nullptr;
bool local_found_real = false;
if (found_real == NULL)
if (found_real == nullptr)
found_real = &local_found_real;
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());
}
if (children.size() != 0)
range = children[0];
range = children[0].get();
} else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) {
if (!id_ast->range_valid) {
if (id_ast->type == AST_AUTOWIRE)
this_width = 1;
else {
// current_ast_mod->dumpAst(NULL, "mod> ");
// current_ast_mod->dumpAst(nullptr, "mod> ");
// log("---\n");
// id_ast->dumpAst(NULL, "decl> ");
// dumpAst(NULL, "ref> ");
// id_ast->dumpAst(nullptr, "decl> ");
// dumpAst(nullptr, "ref> ");
input_error("Failed to detect width of signal access `%s'!\n", str.c_str());
}
} else {
this_width = id_ast->range_left - id_ast->range_right + 1;
if (children.size() != 0)
range = children[0];
range = children[0].get();
}
} else if (id_ast->type == AST_GENVAR) {
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());
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 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) {
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;
delete tmp_range;
} else
input_error("Failed to detect width for identifier %s!\n", str.c_str());
if (range) {
if (range->children.size() == 1)
this_width = 1;
else if (!range->range_valid) {
AstNode *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 left_at_zero_ast = children[0]->children[0]->clone_at_zero();
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 (right_at_zero_ast->simplify(true, 1, -1, false)) { }
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());
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
this_width = range->range_left - range->range_right + 1;
sign_hint = false;
@ -1106,7 +1103,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
break;
case AST_CONCAT:
for (auto child : children) {
for (auto& child : children) {
sub_width_hint = 0;
sub_sign_hint = true;
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_XOR:
case AST_BIT_XNOR:
for (auto child : children)
for (auto& child : children)
child->detectSignWidthWorker(width_hint, sign_hint, found_real);
break;
@ -1175,7 +1172,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_MUL:
case AST_DIV:
case AST_MOD:
for (auto child : children)
for (auto& child : children)
child->detectSignWidthWorker(width_hint, sign_hint, found_real);
break;
@ -1216,12 +1213,13 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
width_hint = max(width_hint, sub_width_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++) {
AstNode *child = children[i];
for (AstNode *v : child->children)
AstNode *child = children[i].get();
for (auto& v : child->children) {
if (v->type != AST_DEFAULT && v->type != AST_BLOCK)
visit_case_expr(v);
visit_case_expr(v.get());
}
}
break;
}
@ -1269,9 +1267,9 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
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());
const AstNode *wire = nullptr;
for (const AstNode *child : func->children)
for (const auto& child : func->children)
if (child->str == func->str) {
wire = child;
wire = child.get();
break;
}
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())
{
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);
AstNode *left = range->children.at(0)->clone();
AstNode *right = range->children.at(1)->clone();
auto left = range->children.at(0)->clone();
auto right = range->children.at(1)->clone();
left->set_in_param_flag(true);
right->set_in_param_flag(true);
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!",
RTLIL::unescape_id(str).c_str());
result_width = abs(int(left->asInt(true) - right->asInt(true)));
delete left;
delete right;
}
width_hint = max(width_hint, result_width);
break;
@ -1306,6 +1302,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
for (auto f : log_files)
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());
}
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
case AST_IDENTIFIER:
{
RTLIL::Wire *wire = NULL;
RTLIL::Wire *wire = nullptr;
RTLIL::SigChunk chunk;
bool is_interface = false;
AST::AstNode *member_node = NULL;
AST::AstNode *member_node = nullptr;
int add_undef_bits_msb = 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) {
AstNode *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 left_at_zero_ast = children[0]->children[0]->clone_at_zero();
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 (right_at_zero_ast->simplify(true, 1, -1, false)) { }
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());
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());
fake_ast->children[0]->delete_children();
if (member_node)
@ -1637,9 +1634,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (GetSize(shift_val) >= 32)
fake_ast->children[1]->is_signed = true;
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;
} else {
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);
for (auto it = children.begin(); it != children.end(); it++) {
AstNode *child = *it;
AstNode *child = it->get();
if (child->type == AST_CELLTYPE) {
cell->type = child->str;
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) {
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)
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);
@ -2114,7 +2108,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (child->type == AST_ARGUMENT) {
RTLIL::SigSpec sig;
if (child->children.size() > 0) {
AstNode *arg = child->children[0];
AstNode *arg = child->children[0].get();
int local_width_hint = -1;
bool local_sign_hint = false;
// 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
case AST_ALWAYS: {
AstNode *always = this->clone();
ProcessGenerator generator(always);
auto always = this->clone();
ProcessGenerator generator(std::move(always));
ignoreThisSignalsInInitial.append(generator.outputSignals);
delete always;
} break;
case AST_INITIAL: {
AstNode *always = this->clone();
ProcessGenerator generator(always, ignoreThisSignalsInInitial);
delete always;
auto always = this->clone();
ProcessGenerator generator(std::move(always), ignoreThisSignalsInInitial);
} break;
case AST_TECALL: {

File diff suppressed because it is too large Load diff