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:
parent
4b8d42d22c
commit
73122921f5
22 changed files with 2496 additions and 2615 deletions
2
Makefile
2
Makefile
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 ];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -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> ¶m) {
|
||||||
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> ¶meters, 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> ¶meters, 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> ¶meters, AstNode **new_ast_out, bool quiet)
|
std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, 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 ¶m : parameters) {
|
for (const auto ¶m : 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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> ¶meters, bool mayfail) override;
|
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, bool mayfail) override;
|
||||||
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, 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> ¶meters, 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> ¶meters, AstNode **new_ast_out, bool quiet = false);
|
std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> ¶meters, 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
|
||||||
|
|
|
@ -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") {
|
||||||
|
|
|
@ -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
3
frontends/verilog/.gitignore
vendored
3
frontends/verilog/.gitignore
vendored
|
@ -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
|
||||||
|
|
|
@ -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 $@)
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
|
@ -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
|
||||||
|
|
|
@ -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
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
(
|
(
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue