3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-08-03 18:00:24 +00:00
This commit is contained in:
Emil J 2025-08-02 14:04:21 +12:00 committed by GitHub
commit 0fd0a9056d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 3694 additions and 3566 deletions

View file

@ -8,7 +8,7 @@ runs:
shell: bash
run: |
sudo apt-get update
sudo apt-get install gperf build-essential bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev
sudo apt-get install gperf build-essential bison flex libfl-dev libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev
- name: Install macOS Dependencies
if: runner.os == 'macOS'

View file

@ -27,6 +27,7 @@ jobs:
with:
submodules: true
persist-credentials: false
- run: sudo apt-get install libfl-dev
- name: Build
run: make vcxsrc YOSYS_VER=latest
- uses: actions/upload-artifact@v4
@ -68,9 +69,20 @@ jobs:
WASI_SDK_URL=https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
if ! [ -d ${WASI_SDK} ]; then curl -L ${WASI_SDK_URL} | tar xzf -; fi
FLEX_VER=2.6.4
FLEX=flex-${FLEX_VER}
FLEX_URL=https://github.com/westes/flex/releases/download/v${FLEX_VER}/${FLEX}.tar.gz
if ! [ -d ${FLEX} ]; then curl -L ${FLEX_URL} | tar xzf -; fi
mkdir -p flex-build
(cd flex-build &&
../${FLEX}/configure --prefix=$(pwd)/../flex-prefix &&
make &&
make install)
mkdir -p build
cat > build/Makefile.conf <<END
export PATH := $(pwd)/${WASI_SDK}/bin:${PATH}
export PATH := $(pwd)/${WASI_SDK}/bin:$(pwd)/flex-prefix/bin:${PATH}
WASI_SYSROOT := $(pwd)/${WASI_SDK}/share/wasi-sysroot
CONFIG := wasi
@ -80,6 +92,8 @@ jobs:
ENABLE_READLINE := 0
ENABLE_PLUGINS := 0
ENABLE_ZLIB := 0
CXXFLAGS += -I$(pwd)/flex-prefix/include
END
make -C build -f ../Makefile CXX=clang -j$(nproc)

View file

@ -133,8 +133,8 @@ ifeq ($(ENABLE_PYOSYS),1)
CXXFLAGS += -I$(BREW_PREFIX)/boost/include
LINKFLAGS += -L$(BREW_PREFIX)/boost/lib -L$(BREW_PREFIX)/boost-python3/lib
endif
CXXFLAGS += -I$(BREW_PREFIX)/readline/include
LINKFLAGS += -L$(BREW_PREFIX)/readline/lib
CXXFLAGS += -I$(BREW_PREFIX)/readline/include -I$(BREW_PREFIX)/flex/include
LINKFLAGS += -L$(BREW_PREFIX)/readline/lib -L$(BREW_PREFIX)/flex/lib
PKG_CONFIG_PATH := $(BREW_PREFIX)/libffi/lib/pkgconfig:$(PKG_CONFIG_PATH)
PKG_CONFIG_PATH := $(BREW_PREFIX)/tcl-tk/lib/pkgconfig:$(PKG_CONFIG_PATH)
export PATH := $(BREW_PREFIX)/bison/bin:$(BREW_PREFIX)/gettext/bin:$(BREW_PREFIX)/flex/bin:$(PATH)

View file

@ -80,10 +80,10 @@ recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make.
TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile).
Xdot (graphviz) is used by the ``show`` command in yosys to display schematics.
For example on Ubuntu Linux 16.04 LTS the following commands will install all
For example on Ubuntu Linux 22.04 LTS the following commands will install all
prerequisites for building yosys:
$ sudo apt-get install build-essential clang lld bison flex \
$ sudo apt-get install build-essential clang lld bison flex libfl-dev \
libreadline-dev gawk tcl-dev libffi-dev git \
graphviz xdot pkg-config python3 libboost-system-dev \
libboost-python-dev libboost-filesystem-dev zlib1g-dev

View file

@ -47,9 +47,9 @@ be found in :file:`frontends/verilog/verilog_lexer.l` in the Yosys source tree.
The lexer does little more than identifying all keywords and literals recognised
by the Yosys Verilog frontend.
The lexer keeps track of the current location in the Verilog source code using
some global variables. These variables are used by the constructor of AST nodes
to annotate each node with the source code location it originated from.
The lexer keeps track of the current location in the Verilog source code with
a ``VerilogLexer::out_loc`` and uses it to construct parser-defined
symbol objects.
Finally the lexer identifies and handles special comments such as "``// synopsys
translate_off``" and "``// synopsys full_case``". (It is recommended to use
@ -178,20 +178,21 @@ properties:
- | Source code location
| Each ``AST::AstNode`` is automatically annotated with the current source
code location by the ``AST::AstNode`` constructor. It is stored in the
``std::string filename`` and ``int linenum`` member variables.
code location by the ``AST::AstNode`` constructor. The ``location`` type
is a manual reimplementation of the bison-provided location type. This
type is defined at ``frontends/verilog/verilog_location.h``.
The ``AST::AstNode`` constructor can be called with up to two child nodes that
are automatically added to the list of child nodes for the new object. This
The ``AST::AstNode`` constructor can be called with up to 4 child nodes. This
simplifies the creation of AST nodes for simple expressions a bit. For example
the bison code for parsing multiplications:
.. code:: none
:number-lines:
basic_expr '*' attr basic_expr {
$$ = new AstNode(AST_MUL, $1, $4);
append_attr($$, $3);
basic_expr TOK_ASTER attr basic_expr {
$$ = std::make_unique<AstNode>(AST_MUL, std::move($1), std::move($4));
SET_AST_NODE_LOC($$.get(), @1, @4);
append_attr($$.get(), $3);
} |
The generated AST data structure is then passed directly to the AST frontend
@ -204,7 +205,7 @@ tree respectively.
Transforming AST to RTLIL
-------------------------
The AST Frontend converts a set of modules in AST representation to modules in
The AST frontend converts a set of modules in AST representation to modules in
RTLIL representation and adds them to the current design. This is done in two
steps: simplification and RTLIL generation.

View file

@ -38,9 +38,7 @@ using namespace AST_INTERNAL;
// instantiate global variables (public API)
namespace AST {
std::string current_filename;
void (*set_line_num)(int) = NULL;
int (*get_line_num)() = NULL;
bool sv_mode_but_global_and_used_for_literally_one_condition;
unsigned long long astnodes = 0;
unsigned long long astnode_count() { return astnodes; }
}
@ -192,16 +190,16 @@ bool AstNode::get_bool_attribute(RTLIL::IdString id)
if (attributes.count(id) == 0)
return false;
AstNode *attr = attributes.at(id);
if (attr->type != AST_CONSTANT)
attr->input_error("Attribute `%s' with non-constant value!\n", id.c_str());
AstNode& attr = *(attributes.at(id));
if (attr.type != AST_CONSTANT)
attr.input_error("Attribute `%s' with non-constant value!\n", id.c_str());
return attr->integer != 0;
return attr.integer != 0;
}
// create new node (AstNode constructor)
// (the optional child arguments make it easier to create AST trees)
AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *child3, AstNode *child4)
AstNode::AstNode(AstSrcLocType loc, AstNodeType type, std::unique_ptr<AstNode> child1, std::unique_ptr<AstNode> child2, std::unique_ptr<AstNode> child3, std::unique_ptr<AstNode> child4)
{
static unsigned int hashidx_count = 123456789;
hashidx_count = mkhash_xorshift(hashidx_count);
@ -209,7 +207,7 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
astnodes++;
this->type = type;
filename = current_filename;
location = loc;
is_input = false;
is_output = false;
is_reg = false;
@ -239,56 +237,73 @@ AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2, AstNode *ch
in_param = false;
if (child1)
children.push_back(child1);
children.push_back(std::move(child1));
if (child2)
children.push_back(child2);
children.push_back(std::move(child2));
if (child3)
children.push_back(child3);
children.push_back(std::move(child3));
if (child4)
children.push_back(child4);
children.push_back(std::move(child4));
fixup_hierarchy_flags();
}
// create a (deep recursive) copy of a node
AstNode *AstNode::clone() const
std::unique_ptr<AstNode> AstNode::clone() const
{
AstNode *that = new AstNode;
*that = *this;
for (auto &it : that->children)
it = it->clone();
for (auto &it : that->attributes)
it.second = it.second->clone();
that->set_in_lvalue_flag(false);
that->set_in_param_flag(false);
that->fixup_hierarchy_flags(); // fixup to set flags on cloned children
auto that = std::make_unique<AstNode>(this->location, this->type);
cloneInto(*that.get());
return that;
}
// create a (deep recursive) copy of a node use 'other' as target root node
void AstNode::cloneInto(AstNode *other) const
void AstNode::cloneInto(AstNode &other) const
{
AstNode *tmp = clone();
tmp->in_lvalue_from_above = other->in_lvalue_from_above;
tmp->in_param_from_above = other->in_param_from_above;
other->delete_children();
*other = *tmp;
tmp->children.clear();
tmp->attributes.clear();
other->fixup_hierarchy_flags();
delete tmp;
other.type = type;
other.str = str;
other.bits = bits;
other.is_input = is_input;
other.is_output = is_output;
other.is_reg = is_reg;
other.is_logic = is_logic;
other.is_signed = is_signed;
other.is_string = is_string;
other.is_wand = is_wand;
other.is_wor = is_wor;
other.range_valid = range_valid;
other.range_swapped = range_swapped;
other.was_checked = was_checked;
other.is_unsized = is_unsized;
other.is_custom_type = is_custom_type;
other.port_id = port_id,
other.range_left = range_left,
other.range_right = range_right;
other.integer = integer;
other.realvalue = realvalue;
other.is_enum = is_enum;
other.dimensions = dimensions;
other.unpacked_dimensions = unpacked_dimensions;
other.id2ast = id2ast;
other.basic_prep = basic_prep;
other.lookahead = lookahead;
other.location = location;
other.in_lvalue = in_lvalue;
other.in_param = in_param;
// Keep in_lvalue_from_above and in_param_from_above untouched
other.delete_children();
for (auto& child : this->children)
other.children.push_back(child->clone());
for (auto& [key, val] : this->attributes)
other.attributes[key] = (val->clone());
// fixup to set flags on cloned children
other.fixup_hierarchy_flags();
}
// delete all children in this node
void AstNode::delete_children()
{
for (auto &it : children)
delete it;
children.clear();
for (auto &it : attributes)
delete it.second;
attributes.clear();
}
@ -423,18 +438,18 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
{
case AST_MODULE:
fprintf(f, "%s" "module %s(", indent.c_str(), id2vl(str).c_str());
for (auto child : children)
for (const auto& child : children)
if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
fprintf(f, "%s%s", first ? "" : ", ", id2vl(child->str).c_str());
first = false;
}
fprintf(f, ");\n");
for (auto child : children)
for (const auto& child : children)
if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM || child->type == AST_DEFPARAM)
child->dumpVlog(f, indent + " ");
else
rem_children1.push_back(child);
rem_children1.push_back(child.get());
for (auto child : rem_children1)
if (child->type == AST_WIRE || child->type == AST_AUTOWIRE || child->type == AST_MEMORY)
@ -470,7 +485,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "%s" "reg", (is_input || is_output) ? " " : indent.c_str());
if (is_signed)
fprintf(f, " signed");
for (auto child : children) {
for (const auto& child : children) {
fprintf(f, " ");
child->dumpVlog(f, "");
}
@ -486,7 +501,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "%s" "memory", indent.c_str());
if (is_signed)
fprintf(f, " signed");
for (auto child : children) {
for (const auto& child : children) {
fprintf(f, " ");
child->dumpVlog(f, "");
if (first)
@ -500,7 +515,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
if (0) { case AST_MEMINIT: txt = "@meminit@"; }
if (0) { case AST_MEMWR: txt = "@memwr@"; }
fprintf(f, "%s%s", indent.c_str(), txt.c_str());
for (auto child : children) {
for (const auto& child : children) {
fprintf(f, first ? "(" : ", ");
child->dumpVlog(f, "");
first = false;
@ -517,7 +532,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
else
fprintf(f, "[%d:%d]", range_left, range_right);
} else {
for (auto child : children) {
for (const auto& child : children) {
fprintf(f, "%c", first ? '[' : ':');
child->dumpVlog(f, "");
first = false;
@ -527,13 +542,13 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
break;
case AST_MULTIRANGE:
for (auto child : children)
for (const auto& child : children)
child->dumpVlog(f, "");
break;
case AST_ALWAYS:
fprintf(f, "%s" "always @", indent.c_str());
for (auto child : children) {
for (const auto& child : children) {
if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
continue;
fprintf(f, first ? "(" : ", ");
@ -541,7 +556,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
first = false;
}
fprintf(f, first ? "*\n" : ")\n");
for (auto child : children) {
for (const auto& child : children) {
if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
child->dumpVlog(f, indent + " ");
}
@ -549,7 +564,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_INITIAL:
fprintf(f, "%s" "initial\n", indent.c_str());
for (auto child : children) {
for (const auto& child : children) {
if (child->type != AST_POSEDGE && child->type != AST_NEGEDGE && child->type != AST_EDGE)
child->dumpVlog(f, indent + " ");
}
@ -562,7 +577,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
fprintf(f, "posedge ");
if (type == AST_NEGEDGE)
fprintf(f, "negedge ");
for (auto child : children)
for (const auto& child : children)
child->dumpVlog(f, "");
break;
@ -574,7 +589,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
else
fprintf(f, "%s", id2vl(str).c_str());
}
for (auto child : children)
for (const auto& child : children)
child->dumpVlog(f, "");
break;
@ -602,7 +617,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
children[0]->dumpVlog(f, indent);
} else {
fprintf(f, "%s" "begin\n", indent.c_str());
for (auto child : children)
for (const auto& child : children)
child->dumpVlog(f, indent + " ");
fprintf(f, "%s" "end\n", indent.c_str());
}
@ -618,7 +633,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
children[0]->dumpVlog(f, "");
fprintf(f, ")\n");
for (size_t i = 1; i < children.size(); i++) {
AstNode *child = children[i];
const auto& child = children[i];
child->dumpVlog(f, indent + " ");
}
fprintf(f, "%s" "endcase\n", indent.c_str());
@ -627,7 +642,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_COND:
case AST_CONDX:
case AST_CONDZ:
for (auto child : children) {
for (const auto& child : children) {
if (child->type == AST_BLOCK) {
fprintf(f, ":\n");
child->dumpVlog(f, indent + " ");
@ -663,7 +678,7 @@ void AstNode::dumpVlog(FILE *f, std::string indent) const
case AST_CONCAT:
fprintf(f, "{");
for (int i = GetSize(children)-1; i >= 0; i--) {
auto child = children[i];
const auto& child = children[i];
if (!first)
fprintf(f, ", ");
child->dumpVlog(f, "");
@ -818,16 +833,16 @@ bool AstNode::contains(const AstNode *other) const
{
if (this == other)
return true;
for (auto child : children)
for (const auto& child : children)
if (child->contains(other))
return true;
return false;
}
// create an AST node for a constant (using a 32 bit int as value)
AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
std::unique_ptr<AstNode> AstNode::mkconst_int(AstSrcLocType loc, uint32_t v, bool is_signed, int width)
{
AstNode *node = new AstNode(AST_CONSTANT);
auto node = std::make_unique<AstNode>(loc, AST_CONSTANT);
node->integer = v;
node->is_signed = is_signed;
for (int i = 0; i < width; i++) {
@ -841,9 +856,9 @@ AstNode *AstNode::mkconst_int(uint32_t v, bool is_signed, int width)
}
// create an AST node for a constant (using a bit vector as value)
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
std::unique_ptr<AstNode> AstNode::mkconst_bits(AstSrcLocType loc, const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized)
{
AstNode *node = new AstNode(AST_CONSTANT);
auto node = std::make_unique<AstNode>(loc, AST_CONSTANT);
node->is_signed = is_signed;
node->bits = v;
for (size_t i = 0; i < 32; i++) {
@ -859,15 +874,15 @@ AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signe
return node;
}
AstNode *AstNode::mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed)
std::unique_ptr<AstNode> AstNode::mkconst_bits(AstSrcLocType loc, const std::vector<RTLIL::State> &v, bool is_signed)
{
return mkconst_bits(v, is_signed, false);
return mkconst_bits(loc, v, is_signed, false);
}
// create an AST node for a constant (using a string in bit vector form as value)
AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
std::unique_ptr<AstNode> AstNode::mkconst_str(AstSrcLocType loc, const std::vector<RTLIL::State> &v)
{
AstNode *node = mkconst_str(RTLIL::Const(v).decode_string());
auto node = mkconst_str(loc, RTLIL::Const(v).decode_string());
while (GetSize(node->bits) < GetSize(v))
node->bits.push_back(RTLIL::State::S0);
log_assert(node->bits == v);
@ -875,14 +890,14 @@ AstNode *AstNode::mkconst_str(const std::vector<RTLIL::State> &v)
}
// create an AST node for a constant (using a string as value)
AstNode *AstNode::mkconst_str(const std::string &str)
std::unique_ptr<AstNode> AstNode::mkconst_str(AstSrcLocType loc, const std::string &str)
{
AstNode *node;
std::unique_ptr<AstNode> node;
// LRM 1364-2005 5.2.3.3 The empty string literal ("") shall be considered
// equivalent to the ASCII NUL ("\0")
if (str.empty()) {
node = AstNode::mkconst_int(0, false, 8);
node = AstNode::mkconst_int(loc, 0, false, 8);
} else {
std::vector<RTLIL::State> data;
data.reserve(str.size() * 8);
@ -893,7 +908,7 @@ AstNode *AstNode::mkconst_str(const std::string &str)
ch = ch >> 1;
}
}
node = AstNode::mkconst_bits(data, false);
node = AstNode::mkconst_bits(loc, data, false);
}
node->is_string = true;
@ -902,18 +917,19 @@ AstNode *AstNode::mkconst_str(const std::string &str)
}
// create a temporary register
AstNode *AstNode::mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed)
std::unique_ptr<AstNode> AstNode::mktemp_logic(AstSrcLocType loc, 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)));
wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++);
auto wire_owned = std::make_unique<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(loc, AST_RANGE, mkconst_int(loc, range_left, true), mkconst_int(loc, range_right, true)));
auto* wire = wire_owned.get();
wire->str = stringf("%s%s:%d$%d", name.c_str(), RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line, autoidx++);
if (nosync)
wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
wire->set_attribute(ID::nosync, AstNode::mkconst_int(loc, 1, false));
wire->is_signed = is_signed;
wire->is_logic = true;
mod->children.push_back(wire);
mod->children.push_back(std::move(wire_owned));
while (wire->simplify(true, 1, -1, false)) { }
AstNode *ident = new AstNode(AST_IDENTIFIER);
auto ident = std::make_unique<AstNode>(loc, AST_IDENTIFIER);
ident->str = wire->str;
ident->id2ast = wire;
@ -967,10 +983,9 @@ RTLIL::Const AstNode::asParaConst() const
{
if (type == AST_REALVALUE)
{
AstNode *strnode = AstNode::mkconst_str(stringf("%f", realvalue));
auto strnode = AstNode::mkconst_str(location, stringf("%f", realvalue));
RTLIL::Const val = strnode->asAttrConst();
val.flags |= RTLIL::CONST_FLAG_REAL;
delete strnode;
return val;
}
@ -1070,7 +1085,7 @@ RTLIL::Const AstNode::realAsConst(int width)
std::string AstNode::loc_string() const
{
return stringf("%s:%d.%d-%d.%d", filename.c_str(), location.first_line, location.first_column, location.last_line, location.last_column);
return stringf("%s:%d.%d-%d.%d", location.begin.filename->c_str(), location.begin.line, location.begin.column, location.end.line, location.end.column);
}
void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
@ -1078,7 +1093,7 @@ void AST::set_src_attr(RTLIL::AttrObject *obj, const AstNode *ast)
obj->attributes[ID::src] = ast->loc_string();
}
static bool param_has_no_default(const AstNode *param) {
static bool param_has_no_default(const std::unique_ptr<AstNode> &param) {
const auto &children = param->children;
log_assert(param->type == AST_PARAMETER);
log_assert(children.size() <= 2);
@ -1086,7 +1101,7 @@ static bool param_has_no_default(const AstNode *param) {
(children.size() == 1 && children[0]->type == AST_RANGE);
}
static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool defer, std::unique_ptr<AstNode> original_ast = NULL, bool quiet = false)
{
log_assert(current_scope.empty());
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);
@ -1100,15 +1115,15 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
AstModule *module = new AstModule;
current_module = module;
module->ast = NULL;
module->ast = nullptr;
module->name = ast->str;
set_src_attr(module, ast);
module->set_bool_attribute(ID::cells_not_processed);
current_ast_mod = ast;
AstNode *ast_before_simplify;
std::unique_ptr<AstNode> ast_before_simplify;
if (original_ast != NULL)
ast_before_simplify = original_ast;
ast_before_simplify = std::move(original_ast);
else
ast_before_simplify = ast->clone();
@ -1125,7 +1140,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (!defer)
{
for (const AstNode *node : ast->children)
for (auto& node : ast->children)
if (node->type == AST_PARAMETER && param_has_no_default(node))
node->input_error("Parameter `%s' has no default value and has not been overridden!\n", node->str.c_str());
@ -1133,7 +1148,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (!blackbox_module && !flag_noblackbox) {
blackbox_module = true;
for (auto child : ast->children) {
for (const auto& child : ast->children) {
if (child->type == AST_WIRE && (child->is_input || child->is_output))
continue;
if (child->type == AST_PARAMETER || child->type == AST_LOCALPARAM)
@ -1163,36 +1178,33 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
ast->dumpVlog(NULL, " ");
log("--- END OF AST DUMP ---\n");
}
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (flag_nowb && ast->attributes.count(ID::whitebox)) {
delete ast->attributes.at(ID::whitebox);
ast->attributes.erase(ID::whitebox);
}
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (ast->attributes.count(ID::lib_whitebox)) {
if (!flag_lib || flag_nowb) {
delete ast->attributes.at(ID::lib_whitebox);
ast->attributes.erase(ID::lib_whitebox);
} else {
if (ast->attributes.count(ID::whitebox)) {
delete ast->attributes.at(ID::whitebox);
ast->attributes.erase(ID::whitebox);
if (flag_lib && !flag_nowb) {
ast->attributes[ID::whitebox] = std::move(
ast->attributes[ID::lib_whitebox]
);
}
AstNode *n = ast->attributes.at(ID::lib_whitebox);
ast->set_attribute(ID::whitebox, n);
ast->attributes.erase(ID::lib_whitebox);
}
}
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (!blackbox_module && ast->attributes.count(ID::blackbox)) {
AstNode *n = ast->attributes.at(ID::blackbox);
auto& n = ast->attributes.at(ID::blackbox);
if (n->type != AST_CONSTANT)
ast->input_error("Got blackbox attribute with non-constant value!\n");
blackbox_module = n->asBool();
}
if (blackbox_module && ast->attributes.count(ID::whitebox)) {
AstNode *n = ast->attributes.at(ID::whitebox);
auto& n = ast->attributes.at(ID::whitebox);
if (n->type != AST_CONSTANT)
ast->input_error("Got whitebox attribute with non-constant value!\n");
blackbox_module = !n->asBool();
@ -1200,62 +1212,59 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
if (ast->attributes.count(ID::noblackbox)) {
if (blackbox_module) {
AstNode *n = ast->attributes.at(ID::noblackbox);
auto& n = ast->attributes.at(ID::noblackbox);
if (n->type != AST_CONSTANT)
ast->input_error("Got noblackbox attribute with non-constant value!\n");
blackbox_module = !n->asBool();
}
delete ast->attributes.at(ID::noblackbox);
ast->attributes.erase(ID::noblackbox);
}
for (auto &attr: ast->attributes)
log_assert((bool)attr.second.get());
if (blackbox_module)
{
if (ast->attributes.count(ID::whitebox)) {
delete ast->attributes.at(ID::whitebox);
ast->attributes.erase(ID::whitebox);
}
if (ast->attributes.count(ID::lib_whitebox)) {
delete ast->attributes.at(ID::lib_whitebox);
ast->attributes.erase(ID::lib_whitebox);
}
std::vector<AstNode*> new_children;
for (auto child : ast->children) {
std::vector<std::unique_ptr<AstNode>> new_children;
for (auto& child : ast->children) {
if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
new_children.push_back(child);
new_children.push_back(std::move(child));
} else if (child->type == AST_PARAMETER) {
new_children.push_back(child);
new_children.push_back(std::move(child));
} else if (child->type == AST_CELL && child->children.size() > 0 && child->children[0]->type == AST_CELLTYPE &&
(child->children[0]->str == "$specify2" || child->children[0]->str == "$specify3" || child->children[0]->str == "$specrule")) {
new_children.push_back(child);
} else {
delete child;
new_children.push_back(std::move(child));
}
}
ast->children.swap(new_children);
if (ast->attributes.count(ID::blackbox) == 0) {
ast->set_attribute(ID::blackbox, AstNode::mkconst_int(1, false));
ast->set_attribute(ID::blackbox, AstNode::mkconst_int(ast->location, 1, false));
}
}
ignoreThisSignalsInInitial = RTLIL::SigSpec();
for (auto &attr : ast->attributes) {
log_assert((bool)attr.second.get());
if (attr.second->type != AST_CONSTANT)
ast->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
module->attributes[attr.first] = attr.second->asAttrConst();
}
for (size_t i = 0; i < ast->children.size(); i++) {
AstNode *node = ast->children[i];
const auto& node = ast->children[i];
if (node->type == AST_WIRE || node->type == AST_MEMORY)
node->genRTLIL();
}
for (size_t i = 0; i < ast->children.size(); i++) {
AstNode *node = ast->children[i];
const auto& node = ast->children[i];
if (node->type != AST_WIRE && node->type != AST_MEMORY && node->type != AST_INITIAL)
node->genRTLIL();
}
@ -1263,7 +1272,7 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
ignoreThisSignalsInInitial.sort_and_unify();
for (size_t i = 0; i < ast->children.size(); i++) {
AstNode *node = ast->children[i];
const auto& node = ast->children[i];
if (node->type == AST_INITIAL)
node->genRTLIL();
}
@ -1277,14 +1286,14 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
continue;
module->attributes[attr.first] = attr.second->asAttrConst();
}
for (const AstNode *node : ast->children)
for (const auto& node : ast->children)
if (node->type == AST_PARAMETER)
current_module->avail_parameters(node->str);
}
if (ast->type == AST_INTERFACE)
module->set_bool_attribute(ID::is_interface);
module->ast = ast_before_simplify;
module->ast = std::move(ast_before_simplify);
module->nolatches = flag_nolatches;
module->nomeminit = flag_nomeminit;
module->nomem2reg = flag_nomem2reg;
@ -1311,8 +1320,8 @@ static RTLIL::Module *process_module(RTLIL::Design *design, AstNode *ast, bool d
RTLIL::Module *
AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
RTLIL::Module *old_module,
AstNode *new_ast,
AstNode *original_ast)
AST::AstNode *new_ast,
std::unique_ptr<AstNode> original_ast)
{
// The old module will be deleted. Rename and mark for deletion, using
// a static counter to make sure we get a unique name.
@ -1335,7 +1344,7 @@ AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
}
// Generate RTLIL from AST for the new module and add to the design:
RTLIL::Module* new_module = process_module(design, new_ast, false, original_ast);
RTLIL::Module* new_module = process_module(design, new_ast, false, std::move(original_ast));
if (is_top)
new_module->set_bool_attribute(ID::top);
@ -1347,17 +1356,17 @@ AST_INTERNAL::process_and_replace_module(RTLIL::Design *design,
static void rename_in_package_stmts(AstNode *pkg)
{
std::unordered_set<std::string> idents;
for (AstNode *item : pkg->children)
for (auto& item : pkg->children)
idents.insert(item->str);
std::function<void(AstNode*)> rename =
[&rename, &idents, pkg](AstNode *node) {
for (AstNode *child : node->children) {
std::function<void(std::unique_ptr<AstNode>&)> rename =
[&rename, &idents, pkg](std::unique_ptr<AstNode>& node) {
for (auto& child : node->children) {
if (idents.count(child->str))
child->str = pkg->str + "::" + child->str.substr(1);
rename(child);
}
};
for (AstNode *item : pkg->children)
for (auto& item : pkg->children)
if (item->type == AST_FUNCTION || item->type == AST_TASK)
rename(item);
}
@ -1390,17 +1399,17 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
ast->fixup_hierarchy_flags(true);
log_assert(current_ast->type == AST_DESIGN);
for (AstNode *child : current_ast->children)
for (const auto& child : current_ast->children)
{
if (child->type == AST_MODULE || child->type == AST_INTERFACE)
{
for (auto n : design->verilog_globals)
for (auto& n : design->verilog_globals)
child->children.push_back(n->clone());
// append nodes from previous packages using package-qualified names
for (auto& n : design->verilog_packages) {
for (auto &o : n->children) {
AstNode *cloned_node = o->clone();
auto cloned_node = o->clone();
// log("cloned node %s\n", type2str(cloned_node->type).c_str());
if (cloned_node->type == AST_ENUM) {
for (auto &e : cloned_node->children) {
@ -1410,7 +1419,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
} else {
cloned_node->str = n->str + std::string("::") + cloned_node->str.substr(1);
}
child->children.push_back(cloned_node);
child->children.push_back(std::move(cloned_node));
}
}
@ -1419,7 +1428,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
bool defer_local = defer;
if (!defer_local)
for (const AstNode *node : child->children)
for (const auto& node : child->children)
if (node->type == AST_PARAMETER && param_has_no_default(node))
{
log("Deferring `%s' because it contains parameter(s) without defaults.\n", child->str.c_str());
@ -1434,7 +1443,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
if (design->has(child->str)) {
RTLIL::Module *existing_mod = design->module(child->str);
if (!nooverwrite && !overwrite && !existing_mod->get_blackbox_attribute()) {
log_file_error(child->filename, child->location.first_line, "Re-definition of module `%s'!\n", child->str.c_str());
log_file_error(*child->location.begin.filename, child->location.begin.line, "Re-definition of module `%s'!\n", child->str.c_str());
} else if (nooverwrite) {
log("Ignoring re-definition of module `%s' at %s.\n",
child->str.c_str(), child->loc_string().c_str());
@ -1447,13 +1456,13 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
}
}
process_module(design, child, defer_local);
process_module(design, child.get(), defer_local);
current_ast_mod = nullptr;
}
else if (child->type == AST_PACKAGE) {
// process enum/other declarations
child->simplify(true, 1, -1, false);
rename_in_package_stmts(child);
rename_in_package_stmts(child.get());
design->verilog_packages.push_back(child->clone());
current_scope.clear();
}
@ -1470,16 +1479,9 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool nodisplay, bool dump
current_scope.clear();
}
}
}
// AstModule destructor
AstModule::~AstModule()
{
if (ast != NULL)
delete ast;
}
// An interface port with modport is specified like this:
// <interface_name>.<modport_name>
// This function splits the interface_name from the modport_name, and fails if it is not a valid combination
@ -1516,7 +1518,7 @@ AstNode * AST::find_modport(AstNode *intf, std::string name)
for (auto &ch : intf->children)
if (ch->type == AST_MODPORT)
if (ch->str == name) // Modport found
return ch;
return ch.get();
return NULL;
}
@ -1524,7 +1526,8 @@ AstNode * AST::find_modport(AstNode *intf, std::string name)
void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule, std::string intfname, AstNode *modport)
{
for (auto w : intfmodule->wires()){
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true)));
auto loc = module_ast->location;
auto wire = std::make_unique<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(loc, AST_RANGE, AstNode::mkconst_int(loc, w->width -1, true), AstNode::mkconst_int(loc, 0, true)));
std::string origname = log_id(w->name);
std::string newname = intfname + "." + origname;
wire->str = newname;
@ -1543,16 +1546,13 @@ void AST::explode_interface_port(AstNode *module_ast, RTLIL::Module * intfmodule
}
}
if (found_in_modport) {
module_ast->children.push_back(wire);
}
else { // If not found in modport, do not create port
delete wire;
module_ast->children.push_back(std::move(wire));
}
}
else { // If no modport, set inout
wire->is_input = true;
wire->is_output = true;
module_ast->children.push_back(wire);
module_ast->children.push_back(std::move(wire));
}
}
}
@ -1570,7 +1570,7 @@ bool AstModule::reprocess_if_necessary(RTLIL::Design *design)
log("Reprocessing module %s because instantiated module %s has become available.\n",
log_id(name), log_id(modname));
loadconfig();
process_and_replace_module(design, this, ast, NULL);
process_and_replace_module(design, this, ast.get(), NULL);
return true;
}
}
@ -1583,32 +1583,33 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
{
loadconfig();
AstNode *new_ast = ast->clone();
auto new_ast = ast->clone();
auto loc = ast->location;
for (auto &intf : local_interfaces) {
std::string intfname = intf.first.str();
RTLIL::Module *intfmodule = intf.second;
for (auto w : intfmodule->wires()){
AstNode *wire = new AstNode(AST_WIRE, new AstNode(AST_RANGE, AstNode::mkconst_int(w->width -1, true), AstNode::mkconst_int(0, true)));
auto wire = std::make_unique<AstNode>(loc, AST_WIRE, std::make_unique<AstNode>(loc, AST_RANGE, AstNode::mkconst_int(loc, w->width -1, true), AstNode::mkconst_int(loc, 0, true)));
std::string newname = log_id(w->name);
newname = intfname + "." + newname;
wire->str = newname;
new_ast->children.push_back(wire);
new_ast->children.push_back(std::move(wire));
}
}
AstNode *ast_before_replacing_interface_ports = new_ast->clone();
auto ast_before_replacing_interface_ports = new_ast->clone();
// Explode all interface ports. Note this will only have an effect on 'top
// level' modules. Other sub-modules will have their interface ports
// exploded via the derive(..) function
for (size_t i =0; i<new_ast->children.size(); i++)
{
AstNode *ch2 = new_ast->children[i];
const auto& ch2 = new_ast->children[i];
if (ch2->type == AST_INTERFACEPORT) { // Is an interface port
std::string name_port = ch2->str; // Name of the interface port
if (ch2->children.size() > 0) {
for(size_t j=0; j<ch2->children.size();j++) {
AstNode *ch = ch2->children[j];
const auto& ch = ch2->children[j];
if(ch->type == AST_INTERFACEPORTTYPE) { // Found the AST node containing the type of the interface
std::pair<std::string,std::string> res = split_modport_from_type(ch->str);
std::string interface_type = res.first;
@ -1616,11 +1617,11 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
if (design->module(interface_type) != nullptr) {
// Add a cell to the module corresponding to the interface port such that
// it can further propagated down if needed:
AstNode *celltype_for_intf = new AstNode(AST_CELLTYPE);
auto celltype_for_intf = std::make_unique<AstNode>(loc, AST_CELLTYPE);
celltype_for_intf->str = interface_type;
AstNode *cell_for_intf = new AstNode(AST_CELL, celltype_for_intf);
auto cell_for_intf = std::make_unique<AstNode>(loc, AST_CELL, std::move(celltype_for_intf));
cell_for_intf->str = name_port + "_inst_from_top_dummy";
new_ast->children.push_back(cell_for_intf);
new_ast->children.push_back(std::move(cell_for_intf));
// Get all members of this non-overridden dummy interface instance:
RTLIL::Module *intfmodule = design->module(interface_type); // All interfaces should at this point in time (assuming
@ -1628,9 +1629,9 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
// present in design->modules_
AstModule *ast_module_of_interface = (AstModule*)intfmodule;
std::string interface_modport_compare_str = "\\" + interface_modport;
AstNode *modport = find_modport(ast_module_of_interface->ast, interface_modport_compare_str); // modport == NULL if no modport
AstNode *modport = find_modport(ast_module_of_interface->ast.get(), interface_modport_compare_str); // modport == NULL if no modport
// Iterate over all wires in the interface and add them to the module:
explode_interface_port(new_ast, intfmodule, name_port, modport);
explode_interface_port(new_ast.get(), intfmodule, name_port, modport);
}
break;
}
@ -1642,9 +1643,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
// Generate RTLIL from AST for the new module and add to the design,
// renaming this module to move it out of the way.
RTLIL::Module* new_module =
process_and_replace_module(design, this, new_ast, ast_before_replacing_interface_ports);
delete new_ast;
process_and_replace_module(design, this, new_ast.get(), std::move(ast_before_replacing_interface_ports));
// Set the attribute "interfaces_replaced_in_module" so that it does not happen again.
new_module->set_bool_attribute(ID::interfaces_replaced_in_module);
@ -1654,7 +1653,7 @@ void AstModule::expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdStr
// This method is used to explode the interface when the interface is a port of the module (not instantiated inside)
RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool /*mayfail*/)
{
AstNode *new_ast = NULL;
std::unique_ptr<AstNode> new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast);
// Since interfaces themselves may be instantiated with different parameters,
@ -1690,14 +1689,14 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
if (modports.count(intfname) > 0) {
std::string interface_modport = modports.at(intfname).str();
AstModule *ast_module_of_interface = (AstModule*)intfmodule;
AstNode *ast_node_of_interface = ast_module_of_interface->ast;
AstNode *ast_node_of_interface = ast_module_of_interface->ast.get();
modport = find_modport(ast_node_of_interface, interface_modport);
}
// Iterate over all wires in the interface and add them to the module:
explode_interface_port(new_ast, intfmodule, intfname, modport);
explode_interface_port(new_ast.get(), intfmodule, intfname, modport);
}
process_module(design, new_ast, false);
process_module(design, new_ast.get(), false);
design->module(modname)->check();
RTLIL::Module* mod = design->module(modname);
@ -1734,7 +1733,6 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
}
delete new_ast;
return modname;
}
@ -1743,18 +1741,17 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, const dict<RTLIL::IdStr
{
bool quiet = lib || attributes.count(ID::blackbox) || attributes.count(ID::whitebox);
AstNode *new_ast = NULL;
std::unique_ptr<AstNode> new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast, quiet);
if (!design->has(modname) && new_ast) {
new_ast->str = modname;
process_module(design, new_ast, false, NULL, quiet);
process_module(design, new_ast.get(), false, NULL, quiet);
design->module(modname)->check();
} else if (!quiet) {
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
}
delete new_ast;
return modname;
}
@ -1784,7 +1781,7 @@ std::string AST::derived_module_name(std::string stripped_name, const std::vecto
}
// create a new parametric module (when needed) and return the name of the generated module
std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet)
std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, std::unique_ptr<AstNode>* new_ast_out, bool quiet)
{
std::string stripped_name = name.str();
(*new_ast_out) = nullptr;
@ -1794,7 +1791,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
int para_counter = 0;
std::vector<std::pair<RTLIL::IdString, RTLIL::Const>> named_parameters;
for (const auto child : ast->children) {
for (const auto& child : ast->children) {
if (child->type != AST_PARAMETER)
continue;
para_counter++;
@ -1828,12 +1825,13 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
pool<IdString> rewritten;
rewritten.reserve(GetSize(parameters));
AstNode *new_ast = ast->clone();
auto new_ast = ast->clone();
auto loc = ast->location;
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(loc, stripped_name.substr(1)));
para_counter = 0;
for (auto child : new_ast->children) {
for (auto& child : new_ast->children) {
if (child->type != AST_PARAMETER)
continue;
para_counter++;
@ -1853,14 +1851,13 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
rewrite_parameter:
if (param_has_no_default(child))
child->children.insert(child->children.begin(), nullptr);
delete child->children.at(0);
if ((it->second.flags & RTLIL::CONST_FLAG_REAL) != 0) {
child->children[0] = new AstNode(AST_REALVALUE);
child->children[0] = std::make_unique<AstNode>(loc, AST_REALVALUE);
child->children[0]->realvalue = std::stod(it->second.decode_string());
} else if ((it->second.flags & RTLIL::CONST_FLAG_STRING) != 0)
child->children[0] = AstNode::mkconst_str(it->second.decode_string());
child->children[0] = AstNode::mkconst_str(loc, it->second.decode_string());
else
child->children[0] = AstNode::mkconst_bits(it->second.to_bits(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0);
child->children[0] = AstNode::mkconst_bits(loc, it->second.to_bits(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0);
rewritten.insert(it->first);
}
@ -1868,17 +1865,17 @@ std::string AstModule::derive_common(RTLIL::Design *design, const dict<RTLIL::Id
for (const auto &param : parameters) {
if (rewritten.count(param.first))
continue;
AstNode *defparam = new AstNode(AST_DEFPARAM, new AstNode(AST_IDENTIFIER));
auto defparam = std::make_unique<AstNode>(loc, AST_DEFPARAM, std::make_unique<AstNode>(loc, AST_IDENTIFIER));
defparam->children[0]->str = param.first.str();
if ((param.second.flags & RTLIL::CONST_FLAG_STRING) != 0)
defparam->children.push_back(AstNode::mkconst_str(param.second.decode_string()));
defparam->children.push_back(AstNode::mkconst_str(loc, param.second.decode_string()));
else
defparam->children.push_back(AstNode::mkconst_bits(param.second.to_bits(), (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0));
new_ast->children.push_back(defparam);
defparam->children.push_back(AstNode::mkconst_bits(loc, param.second.to_bits(), (param.second.flags & RTLIL::CONST_FLAG_SIGNED) != 0));
new_ast->children.push_back(std::move(defparam));
}
new_ast->fixup_hierarchy_flags(true);
(*new_ast_out) = new_ast;
new_ast_out->reset(new_ast.release());
return modname;
}
@ -1928,7 +1925,7 @@ void AstNode::input_error(const char *format, ...) const
{
va_list ap;
va_start(ap, format);
logv_file_error(filename, location.first_line, format, ap);
logv_file_error(*location.begin.filename, location.begin.line, format, ap);
}
YOSYS_NAMESPACE_END

View file

@ -28,6 +28,7 @@
#include "kernel/rtlil.h"
#include "kernel/fmt.h"
#include "frontends/verilog/verilog_location.h"
#include <stdint.h>
#include <set>
@ -162,12 +163,7 @@ namespace AST
AST_BIND
};
struct AstSrcLocType {
unsigned int first_line, last_line;
unsigned int first_column, last_column;
AstSrcLocType() : first_line(0), last_line(0), first_column(0), last_column(0) {}
AstSrcLocType(int _first_line, int _first_column, int _last_line, int _last_column) : first_line(_first_line), last_line(_last_line), first_column(_first_column), last_column(_last_column) {}
};
using AstSrcLocType = location;
// convert an node type to a string (e.g. for debug output)
std::string type2str(AstNodeType type);
@ -183,10 +179,10 @@ namespace AST
AstNodeType type;
// the list of child nodes for this node
std::vector<AstNode*> children;
std::vector<std::unique_ptr<AstNode>> children;
// the list of attributes assigned to this node
std::map<RTLIL::IdString, AstNode*> attributes;
std::map<RTLIL::IdString, std::unique_ptr<AstNode>> attributes;
bool get_bool_attribute(RTLIL::IdString id);
// node content - most of it is unused in most node types
@ -223,7 +219,6 @@ namespace AST
// this is the original sourcecode location that resulted in this AST node
// it is automatically set by the constructor using AST::current_filename and
// the AST::get_line_num() callback function.
std::string filename;
AstSrcLocType location;
// are we embedded in an lvalue, param?
@ -234,9 +229,9 @@ namespace AST
bool in_param_from_above;
// creating and deleting nodes
AstNode(AstNodeType type = AST_NONE, AstNode *child1 = nullptr, AstNode *child2 = nullptr, AstNode *child3 = nullptr, AstNode *child4 = nullptr);
AstNode *clone() const;
void cloneInto(AstNode *other) const;
AstNode(AstSrcLocType loc, AstNodeType type = AST_NONE, std::unique_ptr<AstNode> child1 = nullptr, std::unique_ptr<AstNode> child2 = nullptr, std::unique_ptr<AstNode> child3 = nullptr, std::unique_ptr<AstNode> child4 = nullptr);
std::unique_ptr<AstNode> clone() const;
void cloneInto(AstNode &other) const;
void delete_children();
~AstNode();
@ -264,15 +259,16 @@ namespace AST
// simplify() creates a simpler AST by unrolling for-loops, expanding generate blocks, etc.
// it also sets the id2ast pointers so that identifier lookups are fast in genRTLIL()
bool simplify(bool const_fold, int stage, int width_hint, bool sign_hint);
void null_check();
void replace_result_wire_name_in_function(const std::string &from, const std::string &to);
AstNode *readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
std::unique_ptr<AstNode> readmem(bool is_readmemh, std::string mem_filename, AstNode *memory, int start_addr, int finish_addr, bool unconditional_init);
void expand_genblock(const std::string &prefix);
void label_genblks(std::set<std::string>& existing, int &counter);
void mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg_places,
dict<AstNode*, uint32_t> &mem2reg_flags, dict<AstNode*, uint32_t> &proc_flags, uint32_t &status_flags);
bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode *&async_block);
bool mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod, AstNode *block, AstNode* async_block);
bool mem2reg_check(pool<AstNode*> &mem2reg_set);
void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes);
void mem2reg_remove(pool<AstNode*> &mem2reg_set);
void meminfo(int &mem_width, int &mem_size, int &addr_bits);
bool detect_latch(const std::string &var);
const RTLIL::Module* lookup_cell_module();
@ -288,7 +284,7 @@ namespace AST
};
bool has_const_only_constructs();
bool replace_variables(std::map<std::string, varinfo_t> &variables, AstNode *fcall, bool must_succeed);
AstNode *eval_const_function(AstNode *fcall, bool must_succeed);
std::unique_ptr<AstNode> eval_const_function(AstNode *fcall, bool must_succeed);
bool is_simple_const_expr();
// helper for parsing format strings
@ -305,29 +301,30 @@ namespace AST
std::vector<RTLIL::Binding *> genBindings() const;
// used by genRTLIL() for detecting expression width and sign
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = NULL);
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = NULL);
void detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *found_real = nullptr);
void detectSignWidth(int &width_hint, bool &sign_hint, bool *found_real = nullptr);
// create RTLIL code for this AST node
// for expressions the resulting signal vector is returned
// all generated cell instances, etc. are written to the RTLIL::Module pointed to by AST_INTERNAL::current_module
RTLIL::SigSpec genRTLIL(int width_hint = -1, bool sign_hint = false);
RTLIL::SigSpec genWidthRTLIL(int width, bool sgn, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr = NULL);
RTLIL::SigSpec genWidthRTLIL(int width, bool sgn, const dict<RTLIL::SigBit, RTLIL::SigBit> *new_subst_ptr = nullptr);
// compare AST nodes
bool operator==(const AstNode &other) const;
bool operator!=(const AstNode &other) const;
bool contains(const AstNode *other) const;
AstNode operator=(AstNode) = delete;
// helper functions for creating AST nodes for constants
static AstNode *mkconst_int(uint32_t v, bool is_signed, int width = 32);
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
static AstNode *mkconst_bits(const std::vector<RTLIL::State> &v, bool is_signed);
static AstNode *mkconst_str(const std::vector<RTLIL::State> &v);
static AstNode *mkconst_str(const std::string &str);
static std::unique_ptr<AstNode> mkconst_int(AstSrcLocType loc, uint32_t v, bool is_signed, int width = 32);
static std::unique_ptr<AstNode> mkconst_bits(AstSrcLocType loc, const std::vector<RTLIL::State> &v, bool is_signed, bool is_unsized);
static std::unique_ptr<AstNode> mkconst_bits(AstSrcLocType loc, const std::vector<RTLIL::State> &v, bool is_signed);
static std::unique_ptr<AstNode> mkconst_str(AstSrcLocType loc, const std::vector<RTLIL::State> &v);
static std::unique_ptr<AstNode> mkconst_str(AstSrcLocType loc, const std::string &str);
// helper function to create an AST node for a temporary register
AstNode *mktemp_logic(const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed);
std::unique_ptr<AstNode> mktemp_logic(AstSrcLocType loc, const std::string &name, AstNode *mod, bool nosync, int range_left, int range_right, bool is_signed);
// helper function for creating sign-extended const objects
RTLIL::Const bitsAsConst(int width, bool is_signed);
@ -356,12 +353,12 @@ namespace AST
// helper to clone the node with some of its subexpressions replaced with zero (this is used
// to evaluate widths of dynamic ranges)
AstNode *clone_at_zero();
std::unique_ptr<AstNode> clone_at_zero();
void set_attribute(RTLIL::IdString key, AstNode *node)
void set_attribute(RTLIL::IdString key, std::unique_ptr<AstNode> node)
{
attributes[key] = node;
node->set_in_param_flag(true);
attributes[key] = std::move(node);
}
// helper to set in_lvalue/in_param flags from the hierarchy context (the actual flag
@ -377,7 +374,7 @@ namespace AST
void fixup_hierarchy_flags(bool force_descend = false);
// helpers for indexing
AstNode *make_index_range(AstNode *node, bool unpacked_range = false);
std::unique_ptr<AstNode> make_index_range(AstNode *node, bool unpacked_range = false);
AstNode *get_struct_member() const;
// helper to print errors from simplify/genrtlil code
@ -391,12 +388,11 @@ namespace AST
// parametric modules are supported directly by the AST library
// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
struct AstModule : RTLIL::Module {
AstNode *ast;
std::unique_ptr<AstNode> ast;
bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, pwires, autowire;
~AstModule() override;
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, bool mayfail) override;
RTLIL::IdString derive(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, const dict<RTLIL::IdString, RTLIL::Module*> &interfaces, const dict<RTLIL::IdString, RTLIL::IdString> &modports, bool mayfail) override;
std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, AstNode **new_ast_out, bool quiet = false);
std::string derive_common(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Const> &parameters, std::unique_ptr<AstNode>* new_ast_out, bool quiet = false);
void expand_interfaces(RTLIL::Design *design, const dict<RTLIL::IdString, RTLIL::Module *> &local_interfaces) override;
bool reprocess_if_necessary(RTLIL::Design *design) override;
RTLIL::Module *clone() const override;
@ -406,9 +402,9 @@ namespace AST
// this must be set by the language frontend before parsing the sources
// the AstNode constructor then uses current_filename and get_line_num()
// to initialize the filename and linenum properties of new nodes
extern std::string current_filename;
extern void (*set_line_num)(int);
extern int (*get_line_num)();
// extern std::string current_filename;
// also set by the language frontend to control some AST processing
extern bool sv_mode_but_global_and_used_for_literally_one_condition;
// for stats
unsigned long long astnode_count();
@ -418,7 +414,7 @@ namespace AST
void use_internal_line_num();
// call a DPI function
AstNode *dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args);
std::unique_ptr<AstNode> dpi_call(AstSrcLocType loc, const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<std::unique_ptr<AstNode>> &args);
// Helper functions related to handling SystemVerilog interfaces
std::pair<std::string,std::string> split_modport_from_type(std::string name_type);
@ -464,7 +460,7 @@ namespace AST_INTERNAL
process_and_replace_module(RTLIL::Design *design,
RTLIL::Module *old_module,
AST::AstNode *new_ast,
AST::AstNode *original_ast = nullptr);
std::unique_ptr<AST::AstNode> original_ast = nullptr);
}
YOSYS_NAMESPACE_END

View file

@ -64,9 +64,9 @@ static ffi_fptr resolve_fn (std::string symbol_name)
log_error("unable to resolve '%s'.\n", symbol_name.c_str());
}
AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<AstNode*> &args)
std::unique_ptr<AST::AstNode> AST::dpi_call(AstSrcLocType loc, const std::string &rtype, const std::string &fname, const std::vector<std::string> &argtypes, const std::vector<std::unique_ptr<AST::AstNode>> &args)
{
AST::AstNode *newNode = nullptr;
std::unique_ptr<AST::AstNode> newNode = nullptr;
union value { double f64; float f32; int32_t i32; void *ptr; };
std::vector<value> value_store(args.size() + 1);
std::vector<ffi_type *> types(args.size() + 1);
@ -125,11 +125,11 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname,
ffi_call(&cif, resolve_fn(fname.c_str()), values[args.size()], values.data());
if (rtype == "real") {
newNode = new AstNode(AST_REALVALUE);
newNode = std::make_unique<AstNode>(loc, AST_REALVALUE);
newNode->realvalue = value_store[args.size()].f64;
log(" return realvalue: %g\n", newNode->asReal(true));
} else if (rtype == "shortreal") {
newNode = new AstNode(AST_REALVALUE);
newNode = std::make_unique<AstNode>(loc, AST_REALVALUE);
newNode->realvalue = value_store[args.size()].f32;
log(" return realvalue: %g\n", newNode->asReal(true));
} else if (rtype == "chandle") {
@ -137,10 +137,10 @@ AST::AstNode *AST::dpi_call(const std::string &rtype, const std::string &fname,
std::vector<RTLIL::State> bits(64);
for (int i = 0; i < 64; i++)
bits.at(i) = (rawval & (1ULL << i)) ? RTLIL::State::S1 : RTLIL::State::S0;
newNode = AstNode::mkconst_bits(bits, false);
newNode = AstNode::mkconst_bits(loc, bits, false);
log(" return chandle: %llx\n", (unsigned long long)newNode->asInt(false));
} else {
newNode = AstNode::mkconst_int(value_store[args.size()].i32, false);
newNode = AstNode::mkconst_int(loc, value_store[args.size()].i32, false);
log(" return integer: %lld\n", (long long)newNode->asInt(true));
}
@ -153,7 +153,7 @@ YOSYS_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN
AST::AstNode *AST::dpi_call(const std::string&, const std::string &fname, const std::vector<std::string>&, const std::vector<AstNode*>&)
std::unique_ptr<AST::AstNode> AST::dpi_call(AstSrcLocType, const std::string&, const std::string &fname, const std::vector<std::string>&, const std::vector<std::unique_ptr<AST::AstNode>>&)
{
log_error("Can't call DPI function `%s': this version of yosys is built without plugin support\n", fname.c_str());
}

View file

@ -45,7 +45,7 @@ using namespace AST_INTERNAL;
// helper function for creating RTLIL code for unary operations
static RTLIL::SigSpec uniop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &arg, bool gen_attributes = true)
{
IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++);
IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(*that->location.begin.filename).c_str(), that->location.begin.line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, type);
set_src_attr(cell, that);
@ -77,7 +77,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
return;
}
IdString name = stringf("$extend$%s:%d$%d", RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++);
IdString name = stringf("$extend$%s:%d$%d", RTLIL::encode_filename(*that->location.begin.filename).c_str(), that->location.begin.line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, ID($pos));
set_src_attr(cell, that);
@ -85,7 +85,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
set_src_attr(wire, that);
wire->is_signed = that->is_signed;
if (that != NULL)
if (that != nullptr)
for (auto &attr : that->attributes) {
if (attr.second->type != AST_CONSTANT)
that->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
@ -104,7 +104,7 @@ static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_s
// helper function for creating RTLIL code for binary operations
static RTLIL::SigSpec binop2rtlil(AstNode *that, IdString type, int result_width, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right)
{
IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(that->filename).c_str(), that->location.first_line, autoidx++);
IdString name = stringf("%s$%s:%d$%d", type.c_str(), RTLIL::encode_filename(*that->location.begin.filename).c_str(), that->location.begin.line, autoidx++);
RTLIL::Cell *cell = current_module->addCell(name, type);
set_src_attr(cell, that);
@ -138,7 +138,7 @@ static RTLIL::SigSpec mux2rtlil(AstNode *that, const RTLIL::SigSpec &cond, const
log_assert(cond.size() == 1);
std::stringstream sstr;
sstr << "$ternary$" << RTLIL::encode_filename(that->filename) << ":" << that->location.first_line << "$" << (autoidx++);
sstr << "$ternary$" << RTLIL::encode_filename(*that->location.begin.filename) << ":" << that->location.begin.line << "$" << (autoidx++);
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($mux));
set_src_attr(cell, that);
@ -195,22 +195,22 @@ struct AST_INTERNAL::LookaheadRewriter
if (node->lookahead) {
log_assert(node->type == AST_IDENTIFIER);
if (!lookaheadids.count(node->str)) {
AstNode *wire = new AstNode(AST_WIRE);
for (auto c : node->id2ast->children)
auto wire = std::make_unique<AstNode>(node->location, AST_WIRE);
for (auto& c : node->id2ast->children)
wire->children.push_back(c->clone());
wire->fixup_hierarchy_flags();
wire->str = stringf("$lookahead%s$%d", node->str.c_str(), autoidx++);
wire->set_attribute(ID::nosync, AstNode::mkconst_int(1, false));
wire->set_attribute(ID::nosync, AstNode::mkconst_int(node->location, 1, false));
wire->is_logic = true;
while (wire->simplify(true, 1, -1, false)) { }
current_ast_mod->children.push_back(wire);
lookaheadids[node->str] = make_pair(node->id2ast, wire);
lookaheadids[node->str] = make_pair(node->id2ast, wire.get());
wire->genRTLIL();
current_ast_mod->children.push_back(std::move(wire));
}
}
for (auto child : node->children)
collect_lookaheadids(child);
for (auto& child : node->children)
collect_lookaheadids(child.get());
}
bool has_lookaheadids(AstNode *node)
@ -218,8 +218,8 @@ struct AST_INTERNAL::LookaheadRewriter
if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) != 0)
return true;
for (auto child : node->children)
if (has_lookaheadids(child))
for (auto& child : node->children)
if (has_lookaheadids(child.get()))
return true;
return false;
@ -230,8 +230,8 @@ struct AST_INTERNAL::LookaheadRewriter
if (node->type == AST_IDENTIFIER && lookaheadids.count(node->str) == 0)
return true;
for (auto child : node->children)
if (has_nonlookaheadids(child))
for (auto& child : node->children)
if (has_nonlookaheadids(child.get()))
return true;
return false;
@ -241,16 +241,16 @@ struct AST_INTERNAL::LookaheadRewriter
{
if (node->type == AST_ASSIGN_LE)
{
if (has_lookaheadids(node->children[0]))
if (has_lookaheadids(node->children[0].get()))
{
if (has_nonlookaheadids(node->children[0]))
if (has_nonlookaheadids(node->children[0].get()))
log_error("incompatible mix of lookahead and non-lookahead IDs in LHS expression.\n");
rewrite_lookaheadids(node->children[0], true);
rewrite_lookaheadids(node->children[0].get(), true);
node->type = AST_ASSIGN_EQ;
}
rewrite_lookaheadids(node->children[1], lhs);
rewrite_lookaheadids(node->children[1].get(), lhs);
return;
}
@ -261,21 +261,22 @@ struct AST_INTERNAL::LookaheadRewriter
lhs = false;
}
for (auto child : node->children)
rewrite_lookaheadids(child, lhs);
for (auto& child : node->children)
rewrite_lookaheadids(child.get(), lhs);
}
LookaheadRewriter(AstNode *top)
{
// top->dumpAst(NULL, "REWRITE-BEFORE> ");
// top->dumpVlog(NULL, "REWRITE-BEFORE> ");
// top->dumpAst(nullptr, "REWRITE-BEFORE> ");
// top->dumpVlog(nullptr, "REWRITE-BEFORE> ");
AstNode *block = nullptr;
auto loc = top->location;
for (auto c : top->children)
for (auto& c : top->children)
if (c->type == AST_BLOCK) {
log_assert(block == nullptr);
block = c;
block = c.get();
}
log_assert(block != nullptr);
@ -284,25 +285,25 @@ struct AST_INTERNAL::LookaheadRewriter
for (auto it : lookaheadids)
{
AstNode *ref_orig = new AstNode(AST_IDENTIFIER);
auto ref_orig = std::make_unique<AstNode>(loc, AST_IDENTIFIER);
ref_orig->str = it.second.first->str;
ref_orig->id2ast = it.second.first;
ref_orig->was_checked = true;
AstNode *ref_temp = new AstNode(AST_IDENTIFIER);
auto ref_temp = std::make_unique<AstNode>(loc, AST_IDENTIFIER);
ref_temp->str = it.second.second->str;
ref_temp->id2ast = it.second.second;
ref_temp->was_checked = true;
AstNode *init_assign = new AstNode(AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone());
AstNode *final_assign = new AstNode(AST_ASSIGN_LE, ref_orig, ref_temp);
auto init_assign = std::make_unique<AstNode>(loc, AST_ASSIGN_EQ, ref_temp->clone(), ref_orig->clone());
auto final_assign = std::make_unique<AstNode>(loc, AST_ASSIGN_LE, std::move(ref_orig), std::move(ref_temp));
block->children.insert(block->children.begin(), init_assign);
block->children.push_back(final_assign);
block->children.insert(block->children.begin(), std::move(init_assign));
block->children.push_back(std::move(final_assign));
}
// top->dumpAst(NULL, "REWRITE-AFTER> ");
// top->dumpVlog(NULL, "REWRITE-AFTER> ");
// top->dumpAst(nullptr, "REWRITE-AFTER> ");
// top->dumpVlog(nullptr, "REWRITE-AFTER> ");
}
};
@ -310,7 +311,7 @@ struct AST_INTERNAL::LookaheadRewriter
struct AST_INTERNAL::ProcessGenerator
{
// input and output structures
AstNode *always;
std::unique_ptr<AstNode> always;
RTLIL::SigSpec initSyncSignals;
RTLIL::Process *proc;
RTLIL::SigSpec outputSignals;
@ -341,14 +342,14 @@ struct AST_INTERNAL::ProcessGenerator
// The most recently assigned $print or $check cell \PRIORITY.
int last_effect_priority;
ProcessGenerator(AstNode *always, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(always), initSyncSignals(initSyncSignalsArg), last_effect_priority(0)
ProcessGenerator(std::unique_ptr<AstNode> a, RTLIL::SigSpec initSyncSignalsArg = RTLIL::SigSpec()) : always(std::move(a)), initSyncSignals(initSyncSignalsArg), last_effect_priority(0)
{
// rewrite lookahead references
LookaheadRewriter la_rewriter(always);
LookaheadRewriter la_rewriter(always.get());
// generate process and simple root case
proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(always->filename).c_str(), always->location.first_line, autoidx++));
set_src_attr(proc, always);
proc = current_module->addProcess(stringf("$proc$%s:%d$%d", RTLIL::encode_filename(*always->location.begin.filename).c_str(), always->location.begin.line, autoidx++));
set_src_attr(proc, always.get());
for (auto &attr : always->attributes) {
if (attr.second->type != AST_CONSTANT)
always->input_error("Attribute `%s' with non-constant value!\n", attr.first.c_str());
@ -358,13 +359,13 @@ struct AST_INTERNAL::ProcessGenerator
// create initial temporary signal for all output registers
RTLIL::SigSpec subst_lvalue_from, subst_lvalue_to;
collect_lvalues(subst_lvalue_from, always, true, true);
collect_lvalues(subst_lvalue_from, always.get(), true, true);
subst_lvalue_to = new_temp_signal(subst_lvalue_from);
subst_lvalue_map = subst_lvalue_from.to_sigbit_map(subst_lvalue_to);
bool found_global_syncs = false;
bool found_anyedge_syncs = false;
for (auto child : always->children)
for (auto& child : always->children)
{
if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER &&
child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk)) {
@ -388,7 +389,7 @@ struct AST_INTERNAL::ProcessGenerator
// create syncs for the process
bool found_clocked_sync = false;
for (auto child : always->children)
for (auto& child : always->children)
if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) {
if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast &&
child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute(ID::gclk))
@ -420,9 +421,9 @@ struct AST_INTERNAL::ProcessGenerator
}
// process the AST
for (auto child : always->children)
for (auto& child : always->children)
if (child->type == AST_BLOCK)
processAst(child);
processAst(child.get());
for (auto sync: proc->syncs)
processMemWrites(sync);
@ -472,7 +473,7 @@ struct AST_INTERNAL::ProcessGenerator
for (int i = 0; i < GetSize(chunks); i++)
{
RTLIL::SigChunk &chunk = chunks[i];
if (chunk.wire == NULL)
if (chunk.wire == nullptr)
continue;
std::string wire_name;
@ -484,7 +485,7 @@ struct AST_INTERNAL::ProcessGenerator
} while (current_module->wires_.count(wire_name) > 0);
RTLIL::Wire *wire = current_module->addWire(wire_name, chunk.width);
set_src_attr(wire, always);
set_src_attr(wire, always.get());
chunk.wire = wire;
chunk.offset = 0;
@ -499,10 +500,10 @@ struct AST_INTERNAL::ProcessGenerator
switch (ast->type)
{
case AST_CASE:
for (auto child : ast->children)
for (auto& child : ast->children)
if (child != ast->children[0]) {
log_assert(child->type == AST_COND || child->type == AST_CONDX || child->type == AST_CONDZ);
collect_lvalues(reg, child, type_eq, type_le, false);
collect_lvalues(reg, child.get(), type_eq, type_le, false);
}
break;
@ -511,19 +512,19 @@ struct AST_INTERNAL::ProcessGenerator
case AST_CONDZ:
case AST_ALWAYS:
case AST_INITIAL:
for (auto child : ast->children)
for (auto& child : ast->children)
if (child->type == AST_BLOCK)
collect_lvalues(reg, child, type_eq, type_le, false);
collect_lvalues(reg, child.get(), type_eq, type_le, false);
break;
case AST_BLOCK:
for (auto child : ast->children) {
for (auto& child : ast->children) {
if (child->type == AST_ASSIGN_EQ && type_eq)
reg.append(child->children[0]->genRTLIL());
if (child->type == AST_ASSIGN_LE && type_le)
reg.append(child->children[0]->genRTLIL());
if (child->type == AST_CASE || child->type == AST_BLOCK)
collect_lvalues(reg, child, type_eq, type_le, false);
collect_lvalues(reg, child.get(), type_eq, type_le, false);
}
break;
@ -583,8 +584,8 @@ struct AST_INTERNAL::ProcessGenerator
switch (ast->type)
{
case AST_BLOCK:
for (auto child : ast->children)
processAst(child);
for (auto& child : ast->children)
processAst(child.get());
break;
case AST_ASSIGN_EQ:
@ -641,9 +642,9 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::SigSpec this_case_eq_rvalue = this_case_eq_lvalue;
this_case_eq_rvalue.replace(subst_rvalue_map.stdmap());
RTLIL::CaseRule *default_case = NULL;
RTLIL::CaseRule *last_generated_case = NULL;
for (auto child : ast->children)
RTLIL::CaseRule *default_case = nullptr;
RTLIL::CaseRule *last_generated_case = nullptr;
for (auto& child : ast->children)
{
if (child == ast->children[0])
continue;
@ -657,14 +658,14 @@ struct AST_INTERNAL::ProcessGenerator
RTLIL::CaseRule *backup_case = current_case;
current_case = new RTLIL::CaseRule;
set_src_attr(current_case, child);
set_src_attr(current_case, child.get());
last_generated_case = current_case;
addChunkActions(current_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
for (auto node : child->children) {
for (auto& node : child->children) {
if (node->type == AST_DEFAULT)
default_case = current_case;
else if (node->type == AST_BLOCK)
processAst(node);
processAst(node.get());
else
current_case->compare.push_back(node->genWidthRTLIL(width_hint, sign_hint, &subst_rvalue_map.stdmap()));
}
@ -678,7 +679,7 @@ struct AST_INTERNAL::ProcessGenerator
subst_rvalue_map.restore();
}
if (last_generated_case != NULL && ast->get_bool_attribute(ID::full_case) && default_case == NULL) {
if (last_generated_case != nullptr && ast->get_bool_attribute(ID::full_case) && default_case == nullptr) {
#if 0
// this is a valid transformation, but as optimization it is premature.
// better: add a default case that assigns 'x' to everything, and let later
@ -690,7 +691,7 @@ struct AST_INTERNAL::ProcessGenerator
sw->cases.push_back(default_case);
#endif
} else {
if (default_case == NULL) {
if (default_case == nullptr) {
default_case = new RTLIL::CaseRule;
addChunkActions(default_case->actions, this_case_eq_ltemp, this_case_eq_rvalue);
}
@ -723,7 +724,7 @@ struct AST_INTERNAL::ProcessGenerator
if (ast->str == "$display" || ast->str == "$displayb" || ast->str == "$displayh" || ast->str == "$displayo" ||
ast->str == "$write" || ast->str == "$writeb" || ast->str == "$writeh" || ast->str == "$writeo") {
std::stringstream sstr;
sstr << ast->str << "$" << ast->filename << ":" << ast->location.first_line << "$" << (autoidx++);
sstr << ast->str << "$" << ast->location.begin.filename << ":" << ast->location.begin.line << "$" << (autoidx++);
Wire *en = current_module->addWire(sstr.str() + "_EN", 1);
set_src_attr(en, ast);
@ -760,14 +761,14 @@ struct AST_INTERNAL::ProcessGenerator
default_base = 16;
std::vector<VerilogFmtArg> args;
for (auto node : ast->children) {
for (auto& node : ast->children) {
int width;
bool is_signed;
node->detectSignWidth(width, is_signed, nullptr);
VerilogFmtArg arg = {};
arg.filename = node->filename;
arg.first_line = node->location.first_line;
arg.filename = *node->location.begin.filename;
arg.first_line = node->location.begin.line;
if (node->type == AST_CONSTANT && node->is_string) {
arg.type = VerilogFmtArg::STRING;
arg.str = node->bitsAsConst().decode_string();
@ -793,7 +794,7 @@ struct AST_INTERNAL::ProcessGenerator
fmt.append_literal("\n");
fmt.emit_rtlil(cell);
} else if (!ast->str.empty()) {
log_file_error(ast->filename, ast->location.first_line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str());
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Found unsupported invocation of system task `%s'!\n", ast->str.c_str());
}
break;
@ -813,7 +814,7 @@ struct AST_INTERNAL::ProcessGenerator
IdString cellname;
if (ast->str.empty())
cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(ast->filename).c_str(), ast->location.first_line, autoidx++);
cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(*ast->location.begin.filename).c_str(), ast->location.begin.line, autoidx++);
else
cellname = ast->str;
check_unique_id(current_module, cellname, ast, "procedural assertion");
@ -843,7 +844,7 @@ struct AST_INTERNAL::ProcessGenerator
set_src_attr(cell, ast);
for (auto &attr : ast->attributes) {
if (attr.second->type != AST_CONSTANT)
log_file_error(ast->filename, ast->location.first_line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
log_file_error(*ast->location.begin.filename, ast->location.begin.line, "Attribute `%s' with non-constant value!\n", attr.first.c_str());
cell->attributes[attr.first] = attr.second->asAttrConst();
}
cell->setParam(ID::FLAVOR, flavor);
@ -866,8 +867,8 @@ struct AST_INTERNAL::ProcessGenerator
break;
default:
// ast->dumpAst(NULL, "ast> ");
// current_ast_mod->dumpAst(NULL, "mod> ");
// ast->dumpAst(nullptr, "ast> ");
// current_ast_mod->dumpAst(nullptr, "mod> ");
log_abort();
}
}
@ -876,14 +877,14 @@ struct AST_INTERNAL::ProcessGenerator
{
// Maps per-memid AST_MEMWR IDs to indices in the mem_write_actions array.
dict<std::pair<std::string, int>, int> port_map;
for (auto child : always->children)
for (auto& child : always->children)
if (child->type == AST_MEMWR)
{
std::string memid = child->str;
int portid = child->children[3]->asInt(false);
int cur_idx = GetSize(sync->mem_write_actions);
RTLIL::MemWriteAction action;
set_src_attr(&action, child);
set_src_attr(&action, child.get());
action.memid = memid;
action.address = child->children[0]->genWidthRTLIL(-1, true, &subst_rvalue_map.stdmap());
action.data = child->children[1]->genWidthRTLIL(current_module->memories[memid]->width, true, &subst_rvalue_map.stdmap());
@ -971,11 +972,11 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
bool sub_sign_hint = true;
int sub_width_hint = -1;
int this_width = 0;
AstNode *range = NULL;
AstNode *id_ast = NULL;
AstNode *range = nullptr;
AstNode *id_ast = nullptr;
bool local_found_real = false;
if (found_real == NULL)
if (found_real == nullptr)
found_real = &local_found_real;
switch (type)
@ -1019,22 +1020,22 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
input_error("Failed to detect width for parameter %s!\n", str.c_str());
}
if (children.size() != 0)
range = children[0];
range = children[0].get();
} else if (id_ast->type == AST_WIRE || id_ast->type == AST_AUTOWIRE) {
if (!id_ast->range_valid) {
if (id_ast->type == AST_AUTOWIRE)
this_width = 1;
else {
// current_ast_mod->dumpAst(NULL, "mod> ");
// current_ast_mod->dumpAst(nullptr, "mod> ");
// log("---\n");
// id_ast->dumpAst(NULL, "decl> ");
// dumpAst(NULL, "ref> ");
// id_ast->dumpAst(nullptr, "decl> ");
// dumpAst(nullptr, "ref> ");
input_error("Failed to detect width of signal access `%s'!\n", str.c_str());
}
} else {
this_width = id_ast->range_left - id_ast->range_right + 1;
if (children.size() != 0)
range = children[0];
range = children[0].get();
}
} else if (id_ast->type == AST_GENVAR) {
this_width = 32;
@ -1043,26 +1044,23 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
input_error("Failed to detect width of memory access `%s'!\n", str.c_str());
this_width = id_ast->children[0]->range_left - id_ast->children[0]->range_right + 1;
if (children.size() > 1)
range = children[1];
range = children[1].get();
} else if (id_ast->type == AST_STRUCT_ITEM || id_ast->type == AST_STRUCT || id_ast->type == AST_UNION) {
AstNode *tmp_range = make_index_range(id_ast);
auto tmp_range = make_index_range(id_ast);
this_width = tmp_range->range_left - tmp_range->range_right + 1;
delete tmp_range;
} else
input_error("Failed to detect width for identifier %s!\n", str.c_str());
if (range) {
if (range->children.size() == 1)
this_width = 1;
else if (!range->range_valid) {
AstNode *left_at_zero_ast = children[0]->children[0]->clone_at_zero();
AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone();
auto left_at_zero_ast = children[0]->children[0]->clone_at_zero();
auto right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone();
while (left_at_zero_ast->simplify(true, 1, -1, false)) { }
while (right_at_zero_ast->simplify(true, 1, -1, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
this_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
delete left_at_zero_ast;
delete right_at_zero_ast;
} else
this_width = range->range_left - range->range_right + 1;
sign_hint = false;
@ -1106,7 +1104,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
break;
case AST_CONCAT:
for (auto child : children) {
for (auto& child : children) {
sub_width_hint = 0;
sub_sign_hint = true;
child->detectSignWidthWorker(sub_width_hint, sub_sign_hint);
@ -1135,7 +1133,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_BIT_OR:
case AST_BIT_XOR:
case AST_BIT_XNOR:
for (auto child : children)
for (auto& child : children)
child->detectSignWidthWorker(width_hint, sign_hint, found_real);
break;
@ -1175,7 +1173,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
case AST_MUL:
case AST_DIV:
case AST_MOD:
for (auto child : children)
for (auto& child : children)
child->detectSignWidthWorker(width_hint, sign_hint, found_real);
break;
@ -1216,12 +1214,13 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
width_hint = max(width_hint, sub_width_hint);
sign_hint &= sub_sign_hint;
};
visit_case_expr(children[0]);
visit_case_expr(children[0].get());
for (size_t i = 1; i < children.size(); i++) {
AstNode *child = children[i];
for (AstNode *v : child->children)
AstNode *child = children[i].get();
for (auto& v : child->children) {
if (v->type != AST_DEFAULT && v->type != AST_BLOCK)
visit_case_expr(v);
visit_case_expr(v.get());
}
}
break;
}
@ -1269,9 +1268,9 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (func->type != AST_FUNCTION)
input_error("Function call to %s resolved to something that isn't a function!\n", RTLIL::unescape_id(str).c_str());
const AstNode *wire = nullptr;
for (const AstNode *child : func->children)
for (const auto& child : func->children)
if (child->str == func->str) {
wire = child;
wire = child.get();
break;
}
log_assert(wire && wire->type == AST_WIRE);
@ -1280,10 +1279,10 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
if (!wire->children.empty())
{
log_assert(wire->children.size() == 1);
const AstNode *range = wire->children.at(0);
const AstNode *range = wire->children.at(0).get();
log_assert(range->type == AST_RANGE && range->children.size() == 2);
AstNode *left = range->children.at(0)->clone();
AstNode *right = range->children.at(1)->clone();
auto left = range->children.at(0)->clone();
auto right = range->children.at(1)->clone();
left->set_in_param_flag(true);
right->set_in_param_flag(true);
while (left->simplify(true, 1, -1, false)) { }
@ -1292,8 +1291,6 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
input_error("Function %s has non-constant width!",
RTLIL::unescape_id(str).c_str());
result_width = abs(int(left->asInt(true) - right->asInt(true)));
delete left;
delete right;
}
width_hint = max(width_hint, result_width);
break;
@ -1306,6 +1303,7 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint, bool *foun
for (auto f : log_files)
current_scope_ast->dumpAst(f, "verilog-ast> ");
input_error("Don't know how to detect sign and width for %s node!\n", type2str(type).c_str());
}
if (*found_real)
@ -1342,8 +1340,6 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// be instantiated for this type of AST node.
IdString type_name;
current_filename = filename;
switch (type)
{
// simply ignore this nodes.
@ -1508,7 +1504,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
RTLIL::SigSpec sig = realAsConst(width_hint);
log_file_warning(filename, location.first_line, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
log_file_warning(*location.begin.filename, location.begin.line, "converting real value %e to binary %s.\n", realvalue, log_signal(sig));
return sig;
}
@ -1517,11 +1513,11 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// shifter cell is created and the output signal of this cell is returned
case AST_IDENTIFIER:
{
RTLIL::Wire *wire = NULL;
RTLIL::Wire *wire = nullptr;
RTLIL::SigChunk chunk;
bool is_interface = false;
AST::AstNode *member_node = NULL;
AST::AstNode *member_node = nullptr;
int add_undef_bits_msb = 0;
int add_undef_bits_lsb = 0;
@ -1540,7 +1536,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (dynamic_cast<RTLIL::Binding*>(current_module)) {
/* nothing to do here */
} else if (flag_autowire)
log_file_warning(filename, location.first_line, "Identifier `%s' is implicitly declared.\n", str.c_str());
log_file_warning(*location.begin.filename, location.begin.line, "Identifier `%s' is implicitly declared.\n", str.c_str());
else
input_error("Identifier `%s' is implicitly declared and `default_nettype is set to none.\n", str.c_str());
}
@ -1608,14 +1604,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
if (!children[0]->range_valid) {
AstNode *left_at_zero_ast = children[0]->children[0]->clone_at_zero();
AstNode *right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone();
auto left_at_zero_ast = children[0]->children[0]->clone_at_zero();
auto right_at_zero_ast = children[0]->children.size() >= 2 ? children[0]->children[1]->clone_at_zero() : left_at_zero_ast->clone();
while (left_at_zero_ast->simplify(true, 1, -1, false)) { }
while (right_at_zero_ast->simplify(true, 1, -1, false)) { }
if (left_at_zero_ast->type != AST_CONSTANT || right_at_zero_ast->type != AST_CONSTANT)
input_error("Unsupported expression on dynamic range select on signal `%s'!\n", str.c_str());
int width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1;
AstNode *fake_ast = new AstNode(AST_NONE, clone(), children[0]->children.size() >= 2 ?
auto fake_ast = std::make_unique<AstNode>(children[0]->location, AST_NONE, clone(), children[0]->children.size() >= 2 ?
children[0]->children[1]->clone() : children[0]->children[0]->clone());
fake_ast->children[0]->delete_children();
if (member_node)
@ -1636,10 +1632,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
if (GetSize(shift_val) >= 32)
fake_ast->children[1]->is_signed = true;
RTLIL::SigSpec sig = binop2rtlil(fake_ast, ID($shiftx), width, fake_ast->children[0]->genRTLIL(), shift_val);
delete left_at_zero_ast;
delete right_at_zero_ast;
delete fake_ast;
RTLIL::SigSpec sig = binop2rtlil(fake_ast.get(), ID($shiftx), width, fake_ast->children[0]->genRTLIL(), shift_val);
return sig;
} else {
chunk.width = children[0]->range_left - children[0]->range_right + 1;
@ -1648,10 +1641,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
chunk.offset = source_width - (chunk.offset + chunk.width);
if (chunk.offset > chunk_left || chunk.offset + chunk.width < chunk_right) {
if (chunk.width == 1)
log_file_warning(filename, location.first_line, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
log_file_warning(*location.begin.filename, location.begin.line, "Range select out of bounds on signal `%s': Setting result bit to undef.\n",
str.c_str());
else
log_file_warning(filename, location.first_line, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n",
log_file_warning(*location.begin.filename, location.begin.line, "Range select [%d:%d] out of bounds on signal `%s': Setting all %d result bits to undef.\n",
children[0]->range_left, children[0]->range_right, str.c_str(), chunk.width);
chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
} else {
@ -1665,10 +1658,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
chunk.offset += add_undef_bits_lsb;
}
if (add_undef_bits_lsb)
log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
log_file_warning(*location.begin.filename, location.begin.line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d LSB bits to undef.\n",
children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_lsb);
if (add_undef_bits_msb)
log_file_warning(filename, location.first_line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
log_file_warning(*location.begin.filename, location.begin.line, "Range [%d:%d] select out of bounds on signal `%s': Setting %d MSB bits to undef.\n",
children[0]->range_left, children[0]->range_right, str.c_str(), add_undef_bits_msb);
}
}
@ -1942,7 +1935,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_MEMRD:
{
std::stringstream sstr;
sstr << "$memrd$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
sstr << "$memrd$" << str << "$" << RTLIL::encode_filename(*location.begin.filename) << ":" << location.begin.line << "$" << (autoidx++);
RTLIL::Cell *cell = current_module->addCell(sstr.str(), ID($memrd));
set_src_attr(cell, this);
@ -1980,7 +1973,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
case AST_MEMINIT:
{
std::stringstream sstr;
sstr << "$meminit$" << str << "$" << RTLIL::encode_filename(filename) << ":" << location.first_line << "$" << (autoidx++);
sstr << "$meminit$" << str << "$" << RTLIL::encode_filename(*location.begin.filename) << ":" << location.begin.line << "$" << (autoidx++);
SigSpec en_sig = children[2]->genRTLIL();
@ -2025,7 +2018,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
IdString cellname;
if (str.empty())
cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(filename).c_str(), location.first_line, autoidx++);
cellname = stringf("$%s$%s:%d$%d", flavor.c_str(), RTLIL::encode_filename(*location.begin.filename).c_str(), location.begin.line, autoidx++);
else
cellname = str;
check_unique_id(current_module, cellname, this, "procedural assertion");
@ -2068,7 +2061,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
new_left.append(left[i]);
new_right.append(right[i]);
}
log_file_warning(filename, location.first_line, "Ignoring assignment to constant bits:\n"
log_file_warning(*location.begin.filename, location.begin.line, "Ignoring assignment to constant bits:\n"
" old assignment: %s = %s\n new assignment: %s = %s.\n",
log_signal(left), log_signal(right),
log_signal(new_left), log_signal(new_right));
@ -2092,7 +2085,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
cell->set_bool_attribute(ID::module_not_derived);
for (auto it = children.begin(); it != children.end(); it++) {
AstNode *child = *it;
AstNode *child = it->get();
if (child->type == AST_CELLTYPE) {
cell->type = child->str;
if (flag_icells && cell->type.begins_with("\\$"))
@ -2101,9 +2094,9 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
}
if (child->type == AST_PARASET) {
IdString paraname = child->str.empty() ? stringf("$%d", ++para_counter) : child->str;
const AstNode *value = child->children[0];
const AstNode *value = child->children[0].get();
if (value->type == AST_REALVALUE)
log_file_warning(filename, location.first_line, "Replacing floating point parameter %s.%s = %f with string.\n",
log_file_warning(*location.begin.filename, location.begin.line, "Replacing floating point parameter %s.%s = %f with string.\n",
log_id(cell), log_id(paraname), value->realvalue);
else if (value->type != AST_CONSTANT)
input_error("Parameter %s.%s with non-constant value!\n",
@ -2114,7 +2107,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
if (child->type == AST_ARGUMENT) {
RTLIL::SigSpec sig;
if (child->children.size() > 0) {
AstNode *arg = child->children[0];
AstNode *arg = child->children[0].get();
int local_width_hint = -1;
bool local_sign_hint = false;
// don't inadvertently attempt to detect the width of interfaces
@ -2186,30 +2179,28 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
// use ProcessGenerator for always blocks
case AST_ALWAYS: {
AstNode *always = this->clone();
ProcessGenerator generator(always);
auto always = this->clone();
ProcessGenerator generator(std::move(always));
ignoreThisSignalsInInitial.append(generator.outputSignals);
delete always;
} break;
case AST_INITIAL: {
AstNode *always = this->clone();
ProcessGenerator generator(always, ignoreThisSignalsInInitial);
delete always;
auto always = this->clone();
ProcessGenerator generator(std::move(always), ignoreThisSignalsInInitial);
} break;
case AST_TECALL: {
int sz = children.size();
if (str == "$info") {
if (sz > 0)
log_file_info(filename, location.first_line, "%s.\n", children[0]->str.c_str());
log_file_info(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str.c_str());
else
log_file_info(filename, location.first_line, "\n");
log_file_info(*location.begin.filename, location.begin.line, "\n");
} else if (str == "$warning") {
if (sz > 0)
log_file_warning(filename, location.first_line, "%s.\n", children[0]->str.c_str());
log_file_warning(*location.begin.filename, location.begin.line, "%s.\n", children[0]->str.c_str());
else
log_file_warning(filename, location.first_line, "\n");
log_file_warning(*location.begin.filename, location.begin.line, "\n");
} else if (str == "$error") {
if (sz > 0)
input_error("%s.\n", children[0]->str.c_str());

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,10 @@ frontends/verilog/verilog_parser.tab.cc: frontends/verilog/verilog_parser.y
frontends/verilog/verilog_parser.tab.hh: frontends/verilog/verilog_parser.tab.cc
frontends/verilog/verilog_frontend.o: frontends/verilog/verilog_parser.tab.hh
frontends/verilog/preproc.o: frontends/verilog/verilog_parser.tab.hh
frontends/verilog/verilog_lexer.h: frontends/verilog/verilog_parser.tab.hh
frontends/verilog/verilog_lexer.cc: frontends/verilog/verilog_lexer.l frontends/verilog/verilog_parser.tab.cc
$(Q) mkdir -p $(dir $@)
$(P) flex -o frontends/verilog/verilog_lexer.cc $<
@ -20,5 +24,6 @@ OBJS += frontends/verilog/verilog_parser.tab.o
OBJS += frontends/verilog/verilog_lexer.o
OBJS += frontends/verilog/preproc.o
OBJS += frontends/verilog/verilog_frontend.o
OBJS += frontends/verilog/verilog_error.o
OBJS += frontends/verilog/const2ast.o

View file

@ -42,14 +42,32 @@
YOSYS_NAMESPACE_BEGIN
using namespace AST;
using namespace VERILOG_FRONTEND;
std::string ConstParser::fmt_maybe_loc(std::string msg) {
std::string s;
s += stringf("%s:%d:", loc.begin.filename->c_str(), loc.begin.line);
s += msg;
return s;
}
void ConstParser::log_maybe_loc_error(std::string msg) {
log_error("%s", fmt_maybe_loc(msg).c_str());
}
void ConstParser::log_maybe_loc_warn(std::string msg) {
log_warning("%s", fmt_maybe_loc(msg).c_str());
}
// divide an arbitrary length decimal number by two and return the rest
static int my_decimal_div_by_two(std::vector<uint8_t> &digits)
int ConstParser::my_decimal_div_by_two(std::vector<uint8_t> &digits)
{
int carry = 0;
for (size_t i = 0; i < digits.size(); i++) {
if (digits[i] >= 10)
log_file_error(current_filename, get_line_num(), "Invalid use of [a-fxz?] in decimal constant.\n");
log_maybe_loc_error("Invalid use of [a-fxz?] in decimal constant.\n");
digits[i] += carry * 10;
carry = digits[i] % 2;
digits[i] /= 2;
@ -60,7 +78,7 @@ static int my_decimal_div_by_two(std::vector<uint8_t> &digits)
}
// find the number of significant bits in a binary number (not including the sign bit)
static int my_ilog2(int x)
int ConstParser::my_ilog2(int x)
{
int ret = 0;
while (x != 0 && x != -1) {
@ -71,7 +89,7 @@ static int my_ilog2(int x)
}
// parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?')
static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type, bool is_unsized)
void ConstParser::my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type, bool is_unsized)
{
// all digits in string (MSB at index 0)
std::vector<uint8_t> digits;
@ -102,8 +120,8 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
int bits_per_digit = my_ilog2(base-1);
for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) {
if (*it > (base-1) && *it < 0xf0)
log_file_error(current_filename, get_line_num(), "Digit larger than %d used in in base-%d constant.\n",
base-1, base);
log_maybe_loc_error(stringf("Digit larger than %d used in in base-%d constant.\n",
base-1, base));
for (int i = 0; i < bits_per_digit; i++) {
int bitmask = 1 << i;
if (*it == 0xf0)
@ -126,7 +144,7 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
}
if (is_unsized && (len > len_in_bits))
log_file_error(current_filename, get_line_num(), "Unsized constant must have width of 1 bit, but have %d bits!\n", len);
log_maybe_loc_error(stringf("Unsized constant must have width of 1 bit, but have %d bits!\n", len));
for (len = len - 1; len >= 0; len--)
if (data[len] == State::S1)
@ -140,21 +158,19 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
}
if (len_in_bits == 0)
log_file_error(current_filename, get_line_num(), "Illegal integer constant size of zero (IEEE 1800-2012, 5.7).\n");
log_maybe_loc_error("Illegal integer constant size of zero (IEEE 1800-2012, 5.7).\n");
if (len > len_in_bits)
log_warning("Literal has a width of %d bit, but value requires %d bit. (%s:%d)\n",
len_in_bits, len, current_filename.c_str(), get_line_num());
log_maybe_loc_warn(stringf("Literal has a width of %d bit, but value requires %d bit.\n",
len_in_bits, len));
}
// 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> ConstParser::const2ast(std::string code, char case_type, bool 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())
log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n",
current_filename.c_str(), get_line_num());
log_maybe_loc_warn("Yosys has only limited support for tri-state logic at the moment.\n");
return ret;
}
@ -172,7 +188,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
ch = ch >> 1;
}
}
AstNode *ast = AstNode::mkconst_bits(data, false);
auto ast = AstNode::mkconst_bits(loc, data, false);
ast->str = code;
return ast;
}
@ -191,7 +207,7 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
my_strtobin(data, str, -1, 10, case_type, false);
if (data.back() == State::S1)
data.push_back(State::S0);
return AstNode::mkconst_bits(data, true);
return AstNode::mkconst_bits(loc, data, true);
}
// unsized constant
@ -239,10 +255,11 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
if (is_signed && data.back() == State::S1)
data.push_back(State::S0);
}
return AstNode::mkconst_bits(data, is_signed, is_unsized);
return AstNode::mkconst_bits(loc, data, is_signed, is_unsized);
}
return NULL;
}
YOSYS_NAMESPACE_END

View file

@ -34,6 +34,7 @@
#include "preproc.h"
#include "verilog_frontend.h"
#include "frontends/verilog/verilog_parser.tab.hh"
#include "kernel/log.h"
#include <assert.h>
#include <stack>
@ -749,7 +750,9 @@ frontend_verilog_preproc(std::istream &f,
std::string filename,
const define_map_t &pre_defines,
define_map_t &global_defines_cache,
const std::list<std::string> &include_dirs)
const std::list<std::string> &include_dirs,
ParseState &parse_state,
ParseMode &parse_mode)
{
define_map_t defines;
defines.merge(pre_defines);
@ -961,11 +964,11 @@ frontend_verilog_preproc(std::istream &f,
}
if (tok == "`resetall") {
default_nettype_wire = true;
parse_state.default_nettype_wire = true;
continue;
}
if (tok == "`undefineall" && sv_mode) {
if (tok == "`undefineall" && parse_mode.sv) {
defines.clear();
global_defines_cache.clear();
continue;

View file

@ -35,6 +35,11 @@ YOSYS_NAMESPACE_BEGIN
struct define_body_t;
struct arg_map_t;
namespace VERILOG_FRONTEND {
struct ParseState;
struct ParseMode;
};
struct define_map_t
{
define_map_t();
@ -71,7 +76,9 @@ frontend_verilog_preproc(std::istream &f,
std::string filename,
const define_map_t &pre_defines,
define_map_t &global_defines_cache,
const std::list<std::string> &include_dirs);
const std::list<std::string> &include_dirs,
VERILOG_FRONTEND::ParseState &parse_state,
VERILOG_FRONTEND::ParseMode &parse_mode);
YOSYS_NAMESPACE_END

View file

@ -0,0 +1,52 @@
/*
* yosys -- Yosys Open SYnthesis Suite
*
* Copyright (C) 2012 Claire Xenia Wolf <claire@yosyshq.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ---
*
*/
#include "kernel/yosys_common.h"
#include "frontends/verilog/verilog_error.h"
#include "frontends/verilog/verilog_location.h"
USING_YOSYS_NAMESPACE
/**
* Legacy behavior is to only track lines. Now we have columns too, but we don't
* report them in errors.
* TODO: report columns, too
*/
[[noreturn]]
static void verr_at(std::string filename, int begin_line, char const *fmt, va_list ap)
{
char buffer[1024];
char *p = buffer;
p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
YOSYS_NAMESPACE_PREFIX log_file_error(filename, begin_line, "%s", buffer);
exit(1);
}
[[noreturn]]
void VERILOG_FRONTEND::err_at_loc(location loc, char const *fmt, ...)
{
va_list args;
va_start(args, fmt);
verr_at(loc.begin.filename ? *(loc.begin.filename) : "UNKNOWN", loc.begin.line, fmt, args);
}

View file

@ -0,0 +1,18 @@
#ifndef VERILOG_ERROR_H
#define VERILOG_ERROR_H
#include "kernel/yosys_common.h"
#include "frontends/ast/ast.h"
#include "frontends/verilog/verilog_location.h"
YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND
{
[[noreturn]]
void err_at_loc(location loc, char const *fmt, ...);
};
YOSYS_NAMESPACE_END
#endif

View file

@ -31,10 +31,14 @@
#endif
#include "verilog_frontend.h"
#include "verilog_lexer.h"
#include "verilog_error.h"
#include "verilog_location.h"
#include "preproc.h"
#include "kernel/yosys.h"
#include "libs/sha1/sha1.h"
#include <stdarg.h>
#include <list>
YOSYS_NAMESPACE_BEGIN
using namespace VERILOG_FRONTEND;
@ -47,12 +51,12 @@ static std::list<std::vector<std::string>> verilog_defaults_stack;
static void error_on_dpi_function(AST::AstNode *node)
{
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());
for (auto child : node->children)
error_on_dpi_function(child);
err_at_loc(node->location, "Found DPI function %s.\n", node->str.c_str());
for (auto& child : node->children)
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
// of typedefed names in the packages seen so far.
@ -61,7 +65,7 @@ static void add_package_types(dict<std::string, AST::AstNode *> &user_types, std
for (const auto &node: pkg->children) {
if (node->type == AST::AST_TYPEDEF) {
std::string s = pkg->str + "::" + node->str.substr(1);
user_types[s] = node;
user_types[s] = node.get();
}
}
}
@ -250,6 +254,8 @@ struct VerilogFrontend : public Frontend {
bool flag_dump_vlog1 = false;
bool flag_dump_vlog2 = false;
bool flag_dump_rtlil = false;
bool flag_debug_lexer = false;
bool flag_debug_parser = false;
bool flag_nolatches = false;
bool flag_nomeminit = false;
bool flag_nomem2reg = false;
@ -266,22 +272,24 @@ struct VerilogFrontend : public Frontend {
bool flag_noblackbox = false;
bool flag_nowb = false;
bool flag_nosynthesis = false;
bool flag_yydebug = false;
define_map_t defines_map;
std::list<std::string> include_dirs;
std::list<std::string> attributes;
frontend_verilog_yydebug = false;
sv_mode = false;
formal_mode = false;
noassert_mode = false;
noassume_mode = false;
norestrict_mode = false;
assume_asserts_mode = false;
assert_assumes_mode = false;
lib_mode = false;
specify_mode = false;
default_nettype_wire = true;
ParseMode parse_mode = {};
ParseState parse_state = {};
parse_mode.sv = false;
parse_mode.formal = false;
parse_mode.noassert = false;
parse_mode.noassume = false;
parse_mode.norestrict = false;
parse_mode.assume_asserts = false;
parse_mode.assert_assumes = false;
parse_mode.lib = false;
parse_mode.specify = false;
parse_state.default_nettype_wire = true;
args.insert(args.begin()+1, verilog_defaults.begin(), verilog_defaults.end());
@ -289,11 +297,11 @@ struct VerilogFrontend : public Frontend {
for (argidx = 1; argidx < args.size(); argidx++) {
std::string arg = args[argidx];
if (arg == "-sv") {
sv_mode = true;
parse_mode.sv = true;
continue;
}
if (arg == "-formal") {
formal_mode = true;
parse_mode.formal = true;
continue;
}
if (arg == "-nosynthesis") {
@ -301,23 +309,23 @@ struct VerilogFrontend : public Frontend {
continue;
}
if (arg == "-noassert") {
noassert_mode = true;
parse_mode.noassert = true;
continue;
}
if (arg == "-noassume") {
noassume_mode = true;
parse_mode.noassume = true;
continue;
}
if (arg == "-norestrict") {
norestrict_mode = true;
parse_mode.norestrict = true;
continue;
}
if (arg == "-assume-asserts") {
assume_asserts_mode = true;
parse_mode.assume_asserts = true;
continue;
}
if (arg == "-assert-assumes") {
assert_assumes_mode = true;
parse_mode.assert_assumes = true;
continue;
}
if (arg == "-nodisplay") {
@ -329,7 +337,8 @@ struct VerilogFrontend : public Frontend {
flag_dump_ast2 = true;
flag_dump_vlog1 = true;
flag_dump_vlog2 = true;
frontend_verilog_yydebug = true;
flag_debug_lexer = true;
flag_debug_parser = true;
continue;
}
if (arg == "-dump_ast1") {
@ -357,7 +366,9 @@ struct VerilogFrontend : public Frontend {
continue;
}
if (arg == "-yydebug") {
frontend_verilog_yydebug = true;
flag_yydebug = true;
flag_debug_lexer = true;
flag_debug_parser = true;
continue;
}
if (arg == "-nolatches") {
@ -393,7 +404,7 @@ struct VerilogFrontend : public Frontend {
continue;
}
if (arg == "-lib") {
lib_mode = true;
parse_mode.lib = true;
defines_map.add("BLACKBOX", "");
continue;
}
@ -402,7 +413,7 @@ struct VerilogFrontend : public Frontend {
continue;
}
if (arg == "-specify") {
specify_mode = true;
parse_mode.specify = true;
continue;
}
if (arg == "-noopt") {
@ -432,7 +443,7 @@ struct VerilogFrontend : public Frontend {
continue;
}
if (arg == "-noautowire") {
default_nettype_wire = false;
parse_state.default_nettype_wire = false;
continue;
}
if (arg == "-setattr" && argidx+1 < args.size()) {
@ -469,76 +480,82 @@ struct VerilogFrontend : public Frontend {
break;
}
if (formal_mode || !flag_nosynthesis)
defines_map.add(formal_mode ? "FORMAL" : "SYNTHESIS", "1");
if (parse_mode.formal || !flag_nosynthesis)
defines_map.add(parse_mode.formal ? "FORMAL" : "SYNTHESIS", "1");
extra_args(f, filename, args, argidx);
log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str());
log("Parsing %s%s input from `%s' to AST representation.\n",
formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str());
parse_mode.formal ? "formal " : "", parse_mode.sv ? "SystemVerilog" : "Verilog", filename.c_str());
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);
lexin = f;
AST::sv_mode_but_global_and_used_for_literally_one_condition = parse_mode.sv;
std::string code_after_preproc;
parse_state.lexin = f;
if (!flag_nopp) {
code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, *design->verilog_defines, include_dirs);
code_after_preproc = frontend_verilog_preproc(*f, filename, defines_map, *design->verilog_defines, include_dirs, parse_state, parse_mode);
if (flag_ppdump)
log("-- Verilog code after preprocessor --\n%s-- END OF DUMP --\n", code_after_preproc.c_str());
lexin = new std::istringstream(code_after_preproc);
parse_state.lexin = new std::istringstream(code_after_preproc);
}
auto filename_shared = std::make_shared<std::string>(filename);
auto top_loc = location();
top_loc.begin.filename = filename_shared;
parse_state.current_ast = new AST::AstNode(top_loc, AST::AST_DESIGN);
VerilogLexer lexer(&parse_state, &parse_mode, filename_shared);
frontend_verilog_yy::parser parser(&lexer, &parse_state, &parse_mode);
lexer.set_debug(flag_debug_lexer);
parser.set_debug_level(flag_debug_parser ? 1 : 0);
// make package typedefs available to parser
add_package_types(pkg_user_types, design->verilog_packages);
add_package_types(parse_state.pkg_user_types, design->verilog_packages);
UserTypeMap global_types_map;
for (auto def : design->verilog_globals) {
for (auto& def : design->verilog_globals) {
if (def->type == AST::AST_TYPEDEF) {
global_types_map[def->str] = def;
global_types_map[def->str] = def.get();
}
}
log_assert(user_type_stack.empty());
log_assert(parse_state.user_type_stack.empty());
// use previous global typedefs as bottom level of user type stack
user_type_stack.push_back(std::move(global_types_map));
parse_state.user_type_stack.push_back(std::move(global_types_map));
// add a new empty type map to allow overriding existing global definitions
user_type_stack.push_back(UserTypeMap());
parse_state.user_type_stack.push_back(UserTypeMap());
frontend_verilog_yyset_lineno(1);
frontend_verilog_yyrestart(NULL);
frontend_verilog_yyparse();
frontend_verilog_yylex_destroy();
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 : parse_state.current_ast->children) {
if (child->type == AST::AST_MODULE)
for (auto &attr : attributes)
if (child->attributes.count(attr) == 0)
child->attributes[attr] = AST::AstNode::mkconst_int(1, false);
child->attributes[attr] = AST::AstNode::mkconst_int(top_loc, 1, false);
}
if (flag_nodpi)
error_on_dpi_function(current_ast);
error_on_dpi_function(parse_state.current_ast);
AST::process(design, current_ast, flag_nodisplay, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, lib_mode, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
AST::process(design, parse_state.current_ast, flag_nodisplay, flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches,
flag_nomeminit, flag_nomem2reg, flag_mem2reg, flag_noblackbox, parse_mode.lib, flag_nowb, flag_noopt, flag_icells, flag_pwires, flag_nooverwrite, flag_overwrite, flag_defer, parse_state.default_nettype_wire);
if (!flag_nopp)
delete lexin;
delete parse_state.lexin;
// only the previous and new global type maps remain
log_assert(user_type_stack.size() == 2);
user_type_stack.clear();
log_assert(parse_state.user_type_stack.size() == 2);
parse_state.user_type_stack.clear();
delete current_ast;
current_ast = NULL;
delete parse_state.current_ast;
parse_state.current_ast = NULL;
log("Successfully finished Verilog frontend.\n");
}
@ -760,18 +777,3 @@ struct VerilogFileList : public Pass {
#endif
YOSYS_NAMESPACE_END
// the yyerror function used by bison to report parser errors
void frontend_verilog_yyerror(char const *fmt, ...)
{
va_list ap;
char buffer[1024];
char *p = buffer;
va_start(ap, fmt);
p += vsnprintf(p, buffer + sizeof(buffer) - p, fmt, ap);
va_end(ap);
p += snprintf(p, buffer + sizeof(buffer) - p, "\n");
YOSYS_NAMESPACE_PREFIX log_file_error(YOSYS_NAMESPACE_PREFIX AST::current_filename, frontend_verilog_yyget_lineno(),
"%s", buffer);
exit(1);
}

View file

@ -31,70 +31,34 @@
#include "kernel/yosys.h"
#include "frontends/ast/ast.h"
#include <stdio.h>
#include <stdint.h>
#include <list>
YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND
{
// this variable is set to a new AST_DESIGN node and then filled with the AST by the bison parser
extern struct AST::AstNode *current_ast;
/* Ephemeral context class */
struct ConstParser {
AST::AstSrcLocType loc;
private:
std::string fmt_maybe_loc(std::string msg);
void log_maybe_loc_error(std::string msg);
void log_maybe_loc_warn(std::string msg);
// divide an arbitrary length decimal number by two and return the rest
int my_decimal_div_by_two(std::vector<uint8_t> &digits);
// find the number of significant bits in a binary number (not including the sign bit)
int my_ilog2(int x);
// parse a binary, decimal, hexadecimal or octal number with support for special bits ('x', 'z' and '?')
void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int len_in_bits, int base, char case_type, bool is_unsized);
public:
// convert the Verilog code for a constant to an AST node
std::unique_ptr<AST::AstNode> const2ast(std::string code, char case_type = 0, bool warn_z = false);
// 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);
// names of locally typedef'ed types in a stack
typedef std::map<std::string, AST::AstNode*> UserTypeMap;
extern std::vector<UserTypeMap> user_type_stack;
// names of package typedef'ed types
extern dict<std::string, AST::AstNode*> pkg_user_types;
// state of `default_nettype
extern bool default_nettype_wire;
// running in SystemVerilog mode
extern bool sv_mode;
// running in -formal mode
extern bool formal_mode;
// running in -noassert mode
extern bool noassert_mode;
// running in -noassume mode
extern bool noassume_mode;
// running in -norestrict mode
extern bool norestrict_mode;
// running in -assume-asserts mode
extern bool assume_asserts_mode;
// running in -assert-assumes mode
extern bool assert_assumes_mode;
// running in -lib mode
extern bool lib_mode;
// running in -specify mode
extern bool specify_mode;
// lexer input stream
extern std::istream *lexin;
}
};
};
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

View file

@ -0,0 +1,48 @@
#ifndef VERILOG_LEXER_H
#define VERILOG_LEXER_H
#include "kernel/yosys.h"
#include "frontends/ast/ast.h"
#include "frontends/verilog/verilog_parser.tab.hh"
#include <string>
#include <memory>
#if ! defined(yyFlexLexerOnce)
#define yyFlexLexer frontend_verilog_yyFlexLexer
#include <FlexLexer.h>
#endif
YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND {
using parser = frontend_verilog_yy::parser;
class VerilogLexer : public frontend_verilog_yyFlexLexer {
ParseState* extra;
ParseMode* mode;
public:
parser::location_type out_loc; // TODO private?
VerilogLexer(ParseState* e, ParseMode* m, std::shared_ptr<string> filename) : frontend_verilog_yyFlexLexer(e->lexin), extra(e), mode(m) {
out_loc.begin.filename = filename;
}
~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);
}
private:
std::shared_ptr<std::string> current_filename;
std::vector<std::shared_ptr<std::string>> fn_stack;
std::vector<int> ln_stack;
int LexerInput(char* buf, int max_size) override {
return readsome(*extra->lexin, buf, max_size);
}
};
};
YOSYS_NAMESPACE_END
#endif

View file

@ -32,6 +32,13 @@
*
*/
%option c++
%option yyclass="VerilogLexer"
%option noyywrap
%option nounput
%option yylineno
%option prefix="frontend_verilog_yy"
%{
#ifdef __clang__
@ -41,70 +48,63 @@
#pragma clang diagnostic ignored "-Wmisleading-indentation"
#endif
#include "kernel/log.h"
#include "frontends/verilog/verilog_frontend.h"
#include "frontends/verilog/verilog_lexer.h"
#include "frontends/ast/ast.h"
#include "verilog_parser.tab.hh"
#include "frontends/verilog/verilog_location.h"
#include "kernel/log.h"
#include <vector>
#include <memory>
USING_YOSYS_NAMESPACE
using namespace AST;
using namespace VERILOG_FRONTEND;
#define YYSTYPE FRONTEND_VERILOG_YYSTYPE
#define YYLTYPE FRONTEND_VERILOG_YYLTYPE
using parser = frontend_verilog_yy::parser;
YOSYS_NAMESPACE_BEGIN
namespace VERILOG_FRONTEND {
std::vector<std::string> fn_stack;
std::vector<int> ln_stack;
YYLTYPE real_location;
YYLTYPE old_location;
}
#undef YY_DECL
#define YY_DECL parser::symbol_type VerilogLexer::nextToken()
#undef yyterminate
#define yyterminate() return terminate()
YOSYS_NAMESPACE_END
#define SV_KEYWORD(_tok) \
if (sv_mode) return _tok; \
if (mode->sv) return _tok; \
log("Lexer warning: The SystemVerilog keyword `%s' (at %s:%d) is not "\
"recognized unless read_verilog is called with -sv!\n", yytext, \
AST::current_filename.c_str(), frontend_verilog_yyget_lineno()); \
yylval->string = new std::string(std::string("\\") + yytext); \
return TOK_ID;
"recognized unless read_verilog is called with -sv!\n", YYText(), \
current_filename->c_str(), yylineno); \
string_t val = std::make_unique<std::string>(std::string("\\") + YYText()); \
return parser::make_TOK_ID(std::move(val), out_loc);
#define NON_KEYWORD() \
yylval->string = new std::string(std::string("\\") + yytext); \
return TOK_ID;
string_t val = std::make_unique<std::string>(std::string("\\") + YYText()); \
return parser::make_TOK_ID(std::move(val), out_loc);
#define YY_INPUT(buf,result,max_size) \
result = readsome(*VERILOG_FRONTEND::lexin, buf, max_size)
#define YY_USER_ACTION \
old_location = real_location; \
real_location.first_line = real_location.last_line; \
real_location.first_column = real_location.last_column; \
for(int i = 0; yytext[i] != '\0'; ++i){ \
if(yytext[i] == '\n') { \
real_location.last_line++; \
real_location.last_column = 1; \
out_loc.step(); \
for(int i = 0; YYText()[i] != '\0'; ++i){ \
if(YYText()[i] == '\n') { \
out_loc.lines(); \
} \
else { \
real_location.last_column++; \
out_loc.columns(); \
} \
} \
(*yylloc) = real_location;
out_loc.begin.filename = current_filename; \
out_loc.end.filename = current_filename;
#define YY_BREAK \
(*yylloc) = old_location; \
break;
#undef YY_BUF_SIZE
#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(ParseState* extra, std::string &s)
{
// 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 = extra->user_type_stack.rbegin(); it != extra->user_type_stack.rend(); ++it) {
if (it->count(s) > 0) {
return true;
}
@ -112,7 +112,45 @@ static bool isUserType(std::string &s)
return false;
}
static bool is_hex_dig(char c, int *val)
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:
return parser::make_ch_t(c, loc);
}
}
static bool is_hex_dig(char c, int *val, parser::location_type loc)
{
if ('0' <= c && c <= '9') {
*val = c - '0';
@ -124,7 +162,7 @@ static bool is_hex_dig(char c, int *val)
*val = c - 'A' + 0xA;
return true;
} else if (c == 'x' || c == 'X' || c == 'z' || c == 'Z' || c == '?') {
log_file_warning(AST::current_filename.c_str(), frontend_verilog_yyget_lineno(), "'%c' not a valid digit in hex escape sequence.\n", c);
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "'%c' not a valid digit in hex escape sequence.\n", c);
*val = 0; // not semantically valid in hex escape...
return true; // ...but still processed as part of hex token
}
@ -132,13 +170,13 @@ static bool is_hex_dig(char c, int *val)
return false;
}
static bool is_oct_dig(char c, int *val)
static bool is_oct_dig(char c, int *val, parser::location_type loc)
{
if ('0' <= c && c <= '7') {
*val = c - '0';
return true;
} else if (c == 'x' || c == 'X' || c == 'z' || c == 'Z' || c == '?') {
log_file_warning(AST::current_filename.c_str(), frontend_verilog_yyget_lineno(), "'%c' not a valid digit in octal escape sequence.\n", c);
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "'%c' not a valid digit in octal escape sequence.\n", c);
*val = 0; // not semantically valid in octal escape...
return true; // ...but still processed as part of octal token
}
@ -146,7 +184,7 @@ static bool is_oct_dig(char c, int *val)
return false;
}
static std::string *process_str(char *str, int len, bool triple)
static parser::symbol_type process_str(char *str, int len, bool triple, parser::location_type loc)
{
char *in, *out; // Overwrite input buffer: flex manual states "Actions
// are free to modify 'yytext' except for lengthening it".
@ -158,7 +196,7 @@ static std::string *process_str(char *str, int len, bool triple)
if (in + 1 < str + len && (in[1] ^ *in) == ('\n' ^ '\r'))
in++;
if (!triple)
log_file_warning(AST::current_filename.c_str(), frontend_verilog_yyget_lineno(), "Multi-line string literals should be triple-quoted or escaped.\n");
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "Multi-line string literals should be triple-quoted or escaped.\n");
*out++ = '\n';
break;
case '\\':
@ -186,16 +224,16 @@ static std::string *process_str(char *str, int len, bool triple)
break;
case 'x':
int val;
if (in + 1 < str + len && is_hex_dig(in[1], &val)) {
if (in + 1 < str + len && is_hex_dig(in[1], &val, loc)) {
*out = val;
in++;
if (in + 1 < str + len && is_hex_dig(in[1], &val)) {
if (in + 1 < str + len && is_hex_dig(in[1], &val, loc)) {
*out = *out * 0x10 + val;
in++;
}
out++;
} else
log_file_warning(AST::current_filename.c_str(), frontend_verilog_yyget_lineno(), "ignoring invalid hex escape.\n");
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "ignoring invalid hex escape.\n");
break;
case '\\':
*out++ = '\\';
@ -213,12 +251,12 @@ static std::string *process_str(char *str, int len, bool triple)
int val;
*out = *in - '0';
if (in + 1 < str + len && is_oct_dig(in[1], &val)) {
if (in + 1 < str + len && is_oct_dig(in[1], &val, loc)) {
*out = *out * 010 + val;
in++;
if (in + 1 < str + len && is_oct_dig(in[1], &val)) {
if (in + 1 < str + len && is_oct_dig(in[1], &val, loc)) {
if (*out >= 040)
log_file_warning(AST::current_filename.c_str(), frontend_verilog_yyget_lineno(), "octal escape exceeds \\377\n");
log_file_warning(loc.begin.filename->c_str(), loc.begin.line, "octal escape exceeds \\377\n");
*out = *out * 010 + val;
in++;
}
@ -232,18 +270,11 @@ static std::string *process_str(char *str, int len, bool triple)
*out++ = *in;
}
return new std::string(str, out - str);
return parser::make_TOK_STRING(std::make_unique<std::string>(str, out - str), loc);
}
%}
%option yylineno
%option noyywrap
%option nounput
%option bison-locations
%option bison-bridge
%option prefix="frontend_verilog_yy"
%x COMMENT
%x SYNOPSYS_TRANSLATE_OFF
%x SYNOPSYS_FLAGS
@ -256,47 +287,46 @@ FIXED_POINT_NUMBER_NO_DEC [0-9][0-9_]*[eE][-+]?[0-9_]+
TIME_SCALE_SUFFIX [munpf]?s
%%
// Initialise comment_caller to something to avoid a "maybe undefined"
// warning from GCC.
int comment_caller = INITIAL;
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_push "[^\n]* {
fn_stack.push_back(current_filename);
ln_stack.push_back(frontend_verilog_yyget_lineno());
current_filename = yytext+11;
if (!current_filename.empty() && current_filename.front() == '"')
current_filename = current_filename.substr(1);
if (!current_filename.empty() && current_filename.back() == '"')
current_filename = current_filename.substr(0, current_filename.size()-1);
frontend_verilog_yyset_lineno(0);
yylloc->first_line = yylloc->last_line = 0;
real_location.first_line = real_location.last_line = 0;
ln_stack.push_back(yylineno);
std::string filename = YYText()+11;
if (!filename.empty() && filename.front() == '"')
filename = filename.substr(1);
if (!filename.empty() && filename.back() == '"')
filename = filename.substr(0, filename.size()-1);
current_filename = std::make_shared<std::string>(filename);
yylineno = (0);
out_loc.begin.line = out_loc.end.line = 0;
}
<INITIAL,SYNOPSYS_TRANSLATE_OFF>"`file_pop"[^\n]*\n {
current_filename = fn_stack.back();
fn_stack.pop_back();
frontend_verilog_yyset_lineno(ln_stack.back());
yylloc->first_line = yylloc->last_line = ln_stack.back();
real_location.first_line = real_location.last_line = ln_stack.back();
yylineno = (ln_stack.back());
out_loc.begin.line = out_loc.end.line = ln_stack.back();
ln_stack.pop_back();
}
<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++;
frontend_verilog_yyset_lineno(atoi(p));
yylloc->first_line = yylloc->last_line = atoi(p);
real_location.first_line = real_location.last_line = atoi(p);
yylineno = (atoi(p));
out_loc.begin.line = out_loc.end.line = atoi(p);
while (*p && *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++;
current_filename = std::string(p).substr(1, q-p-1);
current_filename = std::make_shared<std::string>(std::string(p).substr(1, q-p-1));
}
"`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 */
@ -305,222 +335,222 @@ TIME_SCALE_SUFFIX [munpf]?s
"`endcelldefine"[^\n]* /* ignore `endcelldefine */
"`default_nettype"[ \t]+[^ \t\r\n/]+ {
char *p = yytext;
const char *p = YYText();
while (*p != 0 && *p != ' ' && *p != '\t') p++;
while (*p == ' ' || *p == '\t') p++;
if (!strcmp(p, "none"))
VERILOG_FRONTEND::default_nettype_wire = false;
extra->default_nettype_wire = false;
else if (!strcmp(p, "wire"))
VERILOG_FRONTEND::default_nettype_wire = true;
extra->default_nettype_wire = true;
else
frontend_verilog_yyerror("Unsupported default nettype: %s", p);
err_at_loc(out_loc, "Unsupported default nettype: %s", p);
}
"`protect"[^\n]* /* ignore `protect*/
"`endprotect"[^\n]* /* ignore `endprotect*/
"`"[a-zA-Z_$][a-zA-Z0-9_$]* {
frontend_verilog_yyerror("Unimplemented compiler directive or undefined macro %s.", yytext);
err_at_loc(out_loc, "Unimplemented compiler directive or undefined macro %s.", YYText());
}
"module" { return TOK_MODULE; }
"endmodule" { return TOK_ENDMODULE; }
"function" { return TOK_FUNCTION; }
"endfunction" { return TOK_ENDFUNCTION; }
"task" { return TOK_TASK; }
"endtask" { return TOK_ENDTASK; }
"specify" { return specify_mode ? TOK_SPECIFY : TOK_IGNORED_SPECIFY; }
"endspecify" { return TOK_ENDSPECIFY; }
"specparam" { return TOK_SPECPARAM; }
"package" { SV_KEYWORD(TOK_PACKAGE); }
"endpackage" { SV_KEYWORD(TOK_ENDPACKAGE); }
"interface" { SV_KEYWORD(TOK_INTERFACE); }
"endinterface" { SV_KEYWORD(TOK_ENDINTERFACE); }
"modport" { SV_KEYWORD(TOK_MODPORT); }
"parameter" { return TOK_PARAMETER; }
"localparam" { return TOK_LOCALPARAM; }
"defparam" { return TOK_DEFPARAM; }
"assign" { return TOK_ASSIGN; }
"always" { return TOK_ALWAYS; }
"initial" { return TOK_INITIAL; }
"begin" { return TOK_BEGIN; }
"end" { return TOK_END; }
"if" { return TOK_IF; }
"else" { return TOK_ELSE; }
"for" { return TOK_FOR; }
"posedge" { return TOK_POSEDGE; }
"negedge" { return TOK_NEGEDGE; }
"or" { return TOK_OR; }
"case" { return TOK_CASE; }
"casex" { return TOK_CASEX; }
"casez" { return TOK_CASEZ; }
"endcase" { return TOK_ENDCASE; }
"default" { return TOK_DEFAULT; }
"generate" { return TOK_GENERATE; }
"endgenerate" { return TOK_ENDGENERATE; }
"while" { return TOK_WHILE; }
"repeat" { return TOK_REPEAT; }
"automatic" { return TOK_AUTOMATIC; }
"module" { return parser::make_TOK_MODULE(out_loc); }
"endmodule" { return parser::make_TOK_ENDMODULE(out_loc); }
"function" { return parser::make_TOK_FUNCTION(out_loc); }
"endfunction" { return parser::make_TOK_ENDFUNCTION(out_loc); }
"task" { return parser::make_TOK_TASK(out_loc); }
"endtask" { return parser::make_TOK_ENDTASK(out_loc); }
"specify" { return mode->specify ? parser::make_TOK_SPECIFY(out_loc) : parser::make_TOK_IGNORED_SPECIFY(out_loc); }
"endspecify" { return parser::make_TOK_ENDSPECIFY(out_loc); }
"specparam" { return parser::make_TOK_SPECPARAM(out_loc); }
"package" { SV_KEYWORD(parser::make_TOK_PACKAGE(out_loc)); }
"endpackage" { SV_KEYWORD(parser::make_TOK_ENDPACKAGE(out_loc)); }
"interface" { SV_KEYWORD(parser::make_TOK_INTERFACE(out_loc)); }
"endinterface" { SV_KEYWORD(parser::make_TOK_ENDINTERFACE(out_loc)); }
"modport" { SV_KEYWORD(parser::make_TOK_MODPORT(out_loc)); }
"parameter" { return parser::make_TOK_PARAMETER(out_loc); }
"localparam" { return parser::make_TOK_LOCALPARAM(out_loc); }
"defparam" { return parser::make_TOK_DEFPARAM(out_loc); }
"assign" { return parser::make_TOK_ASSIGN(out_loc); }
"always" { return parser::make_TOK_ALWAYS(out_loc); }
"initial" { return parser::make_TOK_INITIAL(out_loc); }
"begin" { return parser::make_TOK_BEGIN(out_loc); }
"end" { return parser::make_TOK_END(out_loc); }
"if" { return parser::make_TOK_IF(out_loc); }
"else" { return parser::make_TOK_ELSE(out_loc); }
"for" { return parser::make_TOK_FOR(out_loc); }
"posedge" { return parser::make_TOK_POSEDGE(out_loc); }
"negedge" { return parser::make_TOK_NEGEDGE(out_loc); }
"or" { return parser::make_TOK_OR(out_loc); }
"case" { return parser::make_TOK_CASE(out_loc); }
"casex" { return parser::make_TOK_CASEX(out_loc); }
"casez" { return parser::make_TOK_CASEZ(out_loc); }
"endcase" { return parser::make_TOK_ENDCASE(out_loc); }
"default" { return parser::make_TOK_DEFAULT(out_loc); }
"generate" { return parser::make_TOK_GENERATE(out_loc); }
"endgenerate" { return parser::make_TOK_ENDGENERATE(out_loc); }
"while" { return parser::make_TOK_WHILE(out_loc); }
"repeat" { return parser::make_TOK_REPEAT(out_loc); }
"automatic" { return parser::make_TOK_AUTOMATIC(out_loc); }
"unique" { SV_KEYWORD(TOK_UNIQUE); }
"unique0" { SV_KEYWORD(TOK_UNIQUE0); }
"priority" { SV_KEYWORD(TOK_PRIORITY); }
"unique" { SV_KEYWORD(parser::make_TOK_UNIQUE(out_loc)); }
"unique0" { SV_KEYWORD(parser::make_TOK_UNIQUE0(out_loc)); }
"priority" { SV_KEYWORD(parser::make_TOK_PRIORITY(out_loc)); }
"always_comb" { SV_KEYWORD(TOK_ALWAYS_COMB); }
"always_ff" { SV_KEYWORD(TOK_ALWAYS_FF); }
"always_latch" { SV_KEYWORD(TOK_ALWAYS_LATCH); }
"always_comb" { SV_KEYWORD(parser::make_TOK_ALWAYS_COMB(out_loc)); }
"always_ff" { SV_KEYWORD(parser::make_TOK_ALWAYS_FF(out_loc)); }
"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
to fix parsing of cells otherwise. (the current cell parser forces a reduce very early to update some
global state.. its a mess) */
[a-zA-Z_$][a-zA-Z0-9_$]*/[ \t\r\n]*:[ \t\r\n]*(assert|assume|cover|restrict)[^a-zA-Z0-9_$\.] {
if (!strcmp(yytext, "default"))
return TOK_DEFAULT;
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_SVA_LABEL;
if (!strcmp(YYText(), "default"))
return parser::make_TOK_DEFAULT(out_loc);
string_t val = std::make_unique<std::string>(std::string("\\") + YYText());
return parser::make_TOK_SVA_LABEL(std::move(val), out_loc);
}
"assert" { if (formal_mode) return TOK_ASSERT; SV_KEYWORD(TOK_ASSERT); }
"assume" { if (formal_mode) return TOK_ASSUME; SV_KEYWORD(TOK_ASSUME); }
"cover" { if (formal_mode) return TOK_COVER; SV_KEYWORD(TOK_COVER); }
"restrict" { if (formal_mode) return TOK_RESTRICT; SV_KEYWORD(TOK_RESTRICT); }
"property" { if (formal_mode) return TOK_PROPERTY; SV_KEYWORD(TOK_PROPERTY); }
"rand" { if (formal_mode) return TOK_RAND; SV_KEYWORD(TOK_RAND); }
"const" { if (formal_mode) return TOK_CONST; SV_KEYWORD(TOK_CONST); }
"checker" { if (formal_mode) return TOK_CHECKER; SV_KEYWORD(TOK_CHECKER); }
"endchecker" { if (formal_mode) return TOK_ENDCHECKER; SV_KEYWORD(TOK_ENDCHECKER); }
"bind" { if (formal_mode) return TOK_BIND; SV_KEYWORD(TOK_BIND); }
"final" { SV_KEYWORD(TOK_FINAL); }
"logic" { SV_KEYWORD(TOK_LOGIC); }
"var" { SV_KEYWORD(TOK_VAR); }
"bit" { SV_KEYWORD(TOK_LOGIC); }
"int" { SV_KEYWORD(TOK_INT); }
"byte" { SV_KEYWORD(TOK_BYTE); }
"shortint" { SV_KEYWORD(TOK_SHORTINT); }
"longint" { SV_KEYWORD(TOK_LONGINT); }
"void" { SV_KEYWORD(TOK_VOID); }
"assert" { if (mode->formal) return parser::make_TOK_ASSERT(out_loc); SV_KEYWORD(parser::make_TOK_ASSERT(out_loc)); }
"assume" { if (mode->formal) return parser::make_TOK_ASSUME(out_loc); SV_KEYWORD(parser::make_TOK_ASSUME(out_loc)); }
"cover" { if (mode->formal) return parser::make_TOK_COVER(out_loc); SV_KEYWORD(parser::make_TOK_COVER(out_loc)); }
"restrict" { if (mode->formal) return parser::make_TOK_RESTRICT(out_loc); SV_KEYWORD(parser::make_TOK_RESTRICT(out_loc)); }
"property" { if (mode->formal) return parser::make_TOK_PROPERTY(out_loc); SV_KEYWORD(parser::make_TOK_PROPERTY(out_loc)); }
"rand" { if (mode->formal) return parser::make_TOK_RAND(out_loc); SV_KEYWORD(parser::make_TOK_RAND(out_loc)); }
"const" { if (mode->formal) return parser::make_TOK_CONST(out_loc); SV_KEYWORD(parser::make_TOK_CONST(out_loc)); }
"checker" { if (mode->formal) return parser::make_TOK_CHECKER(out_loc); SV_KEYWORD(parser::make_TOK_CHECKER(out_loc)); }
"endchecker" { if (mode->formal) return parser::make_TOK_ENDCHECKER(out_loc); SV_KEYWORD(parser::make_TOK_ENDCHECKER(out_loc)); }
"bind" { if (mode->formal) return parser::make_TOK_BIND(out_loc); SV_KEYWORD(parser::make_TOK_BIND(out_loc)); }
"final" { SV_KEYWORD(parser::make_TOK_FINAL(out_loc)); }
"logic" { SV_KEYWORD(parser::make_TOK_LOGIC(out_loc)); }
"var" { SV_KEYWORD(parser::make_TOK_VAR(out_loc)); }
"bit" { SV_KEYWORD(parser::make_TOK_LOGIC(out_loc)); }
"int" { SV_KEYWORD(parser::make_TOK_INT(out_loc)); }
"byte" { SV_KEYWORD(parser::make_TOK_BYTE(out_loc)); }
"shortint" { SV_KEYWORD(parser::make_TOK_SHORTINT(out_loc)); }
"longint" { SV_KEYWORD(parser::make_TOK_LONGINT(out_loc)); }
"void" { SV_KEYWORD(parser::make_TOK_VOID(out_loc)); }
"eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
"s_eventually" { if (formal_mode) return TOK_EVENTUALLY; SV_KEYWORD(TOK_EVENTUALLY); }
"eventually" { if (mode->formal) return parser::make_TOK_EVENTUALLY(out_loc); SV_KEYWORD(parser::make_TOK_EVENTUALLY(out_loc)); }
"s_eventually" { if (mode->formal) return parser::make_TOK_EVENTUALLY(out_loc); SV_KEYWORD(parser::make_TOK_EVENTUALLY(out_loc)); }
"input" { return TOK_INPUT; }
"output" { return TOK_OUTPUT; }
"inout" { return TOK_INOUT; }
"wire" { return TOK_WIRE; }
"tri" { return TOK_WIRE; }
"wor" { return TOK_WOR; }
"trior" { return TOK_WOR; }
"wand" { return TOK_WAND; }
"triand" { return TOK_WAND; }
"reg" { return TOK_REG; }
"integer" { return TOK_INTEGER; }
"signed" { return TOK_SIGNED; }
"unsigned" { SV_KEYWORD(TOK_UNSIGNED); }
"genvar" { return TOK_GENVAR; }
"real" { return TOK_REAL; }
"input" { return parser::make_TOK_INPUT(out_loc); }
"output" { return parser::make_TOK_OUTPUT(out_loc); }
"inout" { return parser::make_TOK_INOUT(out_loc); }
"wire" { return parser::make_TOK_WIRE(out_loc); }
"tri" { return parser::make_TOK_WIRE(out_loc); }
"wor" { return parser::make_TOK_WOR(out_loc); }
"trior" { return parser::make_TOK_WOR(out_loc); }
"wand" { return parser::make_TOK_WAND(out_loc); }
"triand" { return parser::make_TOK_WAND(out_loc); }
"reg" { return parser::make_TOK_REG(out_loc); }
"integer" { return parser::make_TOK_INTEGER(out_loc); }
"signed" { return parser::make_TOK_SIGNED(out_loc); }
"unsigned" { SV_KEYWORD(parser::make_TOK_UNSIGNED(out_loc)); }
"genvar" { return parser::make_TOK_GENVAR(out_loc); }
"real" { return parser::make_TOK_REAL(out_loc); }
"enum" { SV_KEYWORD(TOK_ENUM); }
"typedef" { SV_KEYWORD(TOK_TYPEDEF); }
"struct" { SV_KEYWORD(TOK_STRUCT); }
"union" { SV_KEYWORD(TOK_UNION); }
"packed" { SV_KEYWORD(TOK_PACKED); }
"enum" { SV_KEYWORD(parser::make_TOK_ENUM(out_loc)); }
"typedef" { SV_KEYWORD(parser::make_TOK_TYPEDEF(out_loc)); }
"struct" { SV_KEYWORD(parser::make_TOK_STRUCT(out_loc)); }
"union" { SV_KEYWORD(parser::make_TOK_UNION(out_loc)); }
"packed" { SV_KEYWORD(parser::make_TOK_PACKED(out_loc)); }
{UNSIGNED_NUMBER} {
yylval->string = new std::string(yytext);
return TOK_CONSTVAL;
string_t val = std::make_unique<std::string>(YYText());
return parser::make_TOK_CONSTVAL(std::move(val), out_loc);
}
\'[01zxZX] {
yylval->string = new std::string(yytext);
return TOK_UNBASED_UNSIZED_CONSTVAL;
string_t val = std::make_unique<std::string>(YYText());
return parser::make_TOK_UNBASED_UNSIZED_CONSTVAL(std::move(val), out_loc);
}
\'[sS]?[bodhBODH] {
BEGIN(BASED_CONST);
yylval->string = new std::string(yytext);
return TOK_BASE;
string_t val = std::make_unique<std::string>(YYText());
return parser::make_TOK_BASE(std::move(val), out_loc);
}
<BASED_CONST>[0-9a-fA-FzxZX?][0-9a-fA-FzxZX?_]* {
BEGIN(0);
yylval->string = new std::string(yytext);
return TOK_BASED_CONSTVAL;
string_t val = std::make_unique<std::string>(YYText());
return parser::make_TOK_BASED_CONSTVAL(std::move(val), out_loc);
}
{FIXED_POINT_NUMBER_DEC} {
yylval->string = new std::string(yytext);
return TOK_REALVAL;
string_t val = std::make_unique<std::string>(YYText());
return parser::make_TOK_REALVAL(std::move(val), out_loc);
}
{FIXED_POINT_NUMBER_NO_DEC} {
yylval->string = new std::string(yytext);
return TOK_REALVAL;
string_t val = std::make_unique<std::string>(YYText());
return parser::make_TOK_REALVAL(std::move(val), out_loc);
}
\"([^\\"]|\\.|\\\n)*\" { yylval->string = process_str(yytext + 1, yyleng - 2, false); return TOK_STRING; }
\"([^\\"]|\\.|\\\n)*\" { return process_str(yytext + 1, yyleng - 2, false, out_loc); }
\"{3}(\"{0,2}([^\\"]|\\.|\\\n))*\"{3} { yylval->string = process_str(yytext + 3, yyleng - 6, true); return TOK_STRING; }
\"{3}(\"{0,2}([^\\"]|\\.|\\\n))*\"{3} { return process_str(yytext + 3, yyleng - 6, true, out_loc); }
and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1|notif0|notif1 {
yylval->string = new std::string(yytext);
return TOK_PRIMITIVE;
auto val = std::make_unique<std::string>(YYText());
return parser::make_TOK_PRIMITIVE(std::move(val), out_loc);
}
supply0 { return TOK_SUPPLY0; }
supply1 { return TOK_SUPPLY1; }
supply0 { return parser::make_TOK_SUPPLY0(out_loc); }
supply1 { return parser::make_TOK_SUPPLY1(out_loc); }
"$"(display[bho]?|write[bho]?|strobe|monitor|time|realtime|stop|finish|dumpfile|dumpvars|dumpon|dumpoff|dumpall) {
yylval->string = new std::string(yytext);
return TOK_ID;
auto val = std::make_unique<std::string>(YYText());
return parser::make_TOK_ID(std::move(val), out_loc);
}
"$"(setup|hold|setuphold|removal|recovery|recrem|skew|timeskew|fullskew|nochange) {
if (!specify_mode) REJECT;
yylval->string = new std::string(yytext);
return TOK_ID;
if (!mode->specify) REJECT;
auto val = std::make_unique<std::string>(YYText());
return parser::make_TOK_ID(std::move(val), out_loc);
}
"$"(info|warning|error|fatal) {
yylval->string = new std::string(yytext);
return TOK_MSG_TASKS;
auto val = std::make_unique<std::string>(YYText());
return parser::make_TOK_MSG_TASKS(std::move(val), out_loc);
}
"$signed" { return TOK_TO_SIGNED; }
"$unsigned" { return TOK_TO_UNSIGNED; }
"$signed" { return parser::make_TOK_TO_SIGNED(out_loc); }
"$unsigned" { return parser::make_TOK_TO_UNSIGNED(out_loc); }
[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_$][a-zA-Z0-9_$]* {
// package qualifier
auto s = std::string("\\") + yytext;
if (pkg_user_types.count(s) > 0) {
auto s = std::string("\\") + YYText();
if (extra->pkg_user_types.count(s) > 0) {
// package qualified typedefed name
yylval->string = new std::string(s);
return TOK_PKG_USER_TYPE;
auto val = std::make_unique<std::string>(s);
return parser::make_TOK_PKG_USER_TYPE(std::move(val), out_loc);
}
else {
// backup before :: just return first part
size_t len = strchr(yytext, ':') - yytext;
size_t len = strchr(YYText(), ':') - YYText();
yyless(len);
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID;
auto val = std::make_unique<std::string>(std::string("\\") + YYText());
return parser::make_TOK_ID(std::move(val), out_loc);
}
}
[a-zA-Z_$][a-zA-Z0-9_$]* {
auto s = std::string("\\") + yytext;
if (isUserType(s)) {
auto s = std::string("\\") + YYText();
if (isUserType(extra, s)) {
// previously typedefed name
yylval->string = new std::string(s);
return TOK_USER_TYPE;
auto val = std::make_unique<std::string>(s);
return parser::make_TOK_USER_TYPE(std::move(val), out_loc);
}
else {
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID;
auto val = std::make_unique<std::string>(std::string("\\") + YYText());
return parser::make_TOK_ID(std::move(val), out_loc);
}
}
[a-zA-Z_$][a-zA-Z0-9_$\.]* {
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID;
auto val = std::make_unique<std::string>(std::string("\\") + YYText());
return parser::make_TOK_ID(std::move(val), out_loc);
}
"/*"[ \t]*(synopsys|synthesis)[ \t]*translate_off[ \t]*"*/" {
@ -556,7 +586,7 @@ supply1 { return TOK_SUPPLY1; }
);
printed_warning = true;
}
return TOK_SYNOPSYS_FULL_CASE;
return parser::make_TOK_SYNOPSYS_FULL_CASE(out_loc);
}
<SYNOPSYS_FLAGS>parallel_case {
static bool printed_warning = false;
@ -570,119 +600,115 @@ supply1 { return TOK_SUPPLY1; }
);
printed_warning = true;
}
return TOK_SYNOPSYS_PARALLEL_CASE;
return parser::make_TOK_SYNOPSYS_PARALLEL_CASE(out_loc);
}
<SYNOPSYS_FLAGS>. /* ignore everything else */
<SYNOPSYS_FLAGS>"*/" { BEGIN(0); }
import[ \t\r\n]+\"(DPI|DPI-C)\"[ \t\r\n]+function[ \t\r\n]+ {
BEGIN(IMPORT_DPI);
return TOK_DPI_FUNCTION;
return parser::make_TOK_DPI_FUNCTION(out_loc);
}
<IMPORT_DPI>[a-zA-Z_$][a-zA-Z0-9_$]* {
yylval->string = new std::string(std::string("\\") + yytext);
return TOK_ID;
auto val = std::make_unique<std::string>(std::string("\\") + YYText());
return parser::make_TOK_ID(std::move(val), out_loc);
}
<IMPORT_DPI>[ \t\r\n] /* ignore whitespaces */
<IMPORT_DPI>";" {
BEGIN(0);
return *yytext;
return char_tok(*YYText(), out_loc);
}
<IMPORT_DPI>. {
return *yytext;
return char_tok(*YYText(), out_loc);
}
"\\"[^ \t\r\n]+ {
yylval->string = new std::string(yytext);
return TOK_ID;
auto val = std::make_unique<std::string>(YYText());
return parser::make_TOK_ID(std::move(val), out_loc);
}
"(*" { return ATTR_BEGIN; }
"*)" { return ATTR_END; }
"(*" { return parser::make_ATTR_BEGIN(out_loc); }
"*)" { return parser::make_ATTR_END(out_loc); }
"{*" { return DEFATTR_BEGIN; }
"*}" { return DEFATTR_END; }
"{*" { return parser::make_DEFATTR_BEGIN(out_loc); }
"*}" { return parser::make_DEFATTR_END(out_loc); }
"**" { return OP_POW; }
"||" { return OP_LOR; }
"&&" { return OP_LAND; }
"==" { return OP_EQ; }
"!=" { return OP_NE; }
"<=" { return OP_LE; }
">=" { return OP_GE; }
"**" { return parser::make_OP_POW(out_loc); }
"||" { return parser::make_OP_LOR(out_loc); }
"&&" { return parser::make_OP_LAND(out_loc); }
"==" { return parser::make_OP_EQ(out_loc); }
"!=" { return parser::make_OP_NE(out_loc); }
"<=" { return parser::make_OP_LE(out_loc); }
">=" { return parser::make_OP_GE(out_loc); }
"===" { return OP_EQX; }
"!==" { return OP_NEX; }
"===" { return parser::make_OP_EQX(out_loc); }
"!==" { return parser::make_OP_NEX(out_loc); }
"~&" { return OP_NAND; }
"~|" { return OP_NOR; }
"~^" { return OP_XNOR; }
"^~" { return OP_XNOR; }
"~&" { return parser::make_OP_NAND(out_loc); }
"~|" { return parser::make_OP_NOR(out_loc); }
"~^" { return parser::make_OP_XNOR(out_loc); }
"^~" { return parser::make_OP_XNOR(out_loc); }
"<<" { return OP_SHL; }
">>" { return OP_SHR; }
"<<<" { return OP_SSHL; }
">>>" { return OP_SSHR; }
"<<" { return parser::make_OP_SHL(out_loc); }
">>" { return parser::make_OP_SHR(out_loc); }
"<<<" { return parser::make_OP_SSHL(out_loc); }
">>>" { return parser::make_OP_SSHR(out_loc); }
"'" { return OP_CAST; }
"'" { return parser::make_OP_CAST(out_loc); }
"::" { return TOK_PACKAGESEP; }
"++" { return TOK_INCREMENT; }
"--" { return TOK_DECREMENT; }
"::" { return parser::make_TOK_PACKAGESEP(out_loc); }
"++" { return parser::make_TOK_INCREMENT(out_loc); }
"--" { return parser::make_TOK_DECREMENT(out_loc); }
"+:" { return TOK_POS_INDEXED; }
"-:" { return TOK_NEG_INDEXED; }
"+:" { return parser::make_TOK_POS_INDEXED(out_loc); }
"-:" { 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(TOK_BIT_AND_ASSIGN); }
"+=" { SV_KEYWORD(TOK_ADD_ASSIGN); }
"-=" { SV_KEYWORD(TOK_SUB_ASSIGN); }
"^=" { SV_KEYWORD(TOK_BIT_XOR_ASSIGN); }
"/=" { SV_KEYWORD(TOK_DIV_ASSIGN); }
"%=" { SV_KEYWORD(TOK_MOD_ASSIGN); }
"*=" { SV_KEYWORD(TOK_MUL_ASSIGN); }
"<<=" { SV_KEYWORD(TOK_SHL_ASSIGN); }
">>=" { SV_KEYWORD(TOK_SHR_ASSIGN); }
"<<<=" { SV_KEYWORD(TOK_SSHL_ASSIGN); }
">>>=" { SV_KEYWORD(TOK_SSHR_ASSIGN); }
"|=" { SV_KEYWORD(parser::make_TOK_BIT_OR_ASSIGN(out_loc)); }
"&=" { SV_KEYWORD(parser::make_TOK_BIT_AND_ASSIGN(out_loc)); }
"+=" { SV_KEYWORD(parser::make_TOK_ADD_ASSIGN(out_loc)); }
"-=" { SV_KEYWORD(parser::make_TOK_SUB_ASSIGN(out_loc)); }
"^=" { SV_KEYWORD(parser::make_TOK_BIT_XOR_ASSIGN(out_loc)); }
"/=" { SV_KEYWORD(parser::make_TOK_DIV_ASSIGN(out_loc)); }
"%=" { SV_KEYWORD(parser::make_TOK_MOD_ASSIGN(out_loc)); }
"*=" { SV_KEYWORD(parser::make_TOK_MUL_ASSIGN(out_loc)); }
"<<=" { SV_KEYWORD(parser::make_TOK_SHL_ASSIGN(out_loc)); }
">>=" { SV_KEYWORD(parser::make_TOK_SHR_ASSIGN(out_loc)); }
"<<<=" { SV_KEYWORD(parser::make_TOK_SSHL_ASSIGN(out_loc)); }
">>>=" { SV_KEYWORD(parser::make_TOK_SSHR_ASSIGN(out_loc)); }
[-+]?[=*]> {
if (!specify_mode) REJECT;
yylval->string = new std::string(yytext);
return TOK_SPECIFY_OPER;
if (!mode->specify) REJECT;
auto val = std::make_unique<std::string>(YYText());
return parser::make_TOK_SPECIFY_OPER(std::move(val), out_loc);
}
"&&&" {
if (!specify_mode) return TOK_IGNORED_SPECIFY_AND;
return TOK_SPECIFY_AND;
if (!mode->specify) return parser::make_TOK_IGNORED_SPECIFY_AND(out_loc);
return parser::make_TOK_SPECIFY_AND(out_loc);
}
{UNSIGNED_NUMBER}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; }
{FIXED_POINT_NUMBER_DEC}{TIME_SCALE_SUFFIX} { return TOK_TIME_SCALE; }
{FIXED_POINT_NUMBER_NO_DEC}{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 parser::make_TOK_TIME_SCALE(out_loc); }
{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); }
<COMMENT>. /* ignore comment body */
<COMMENT>\n /* ignore comment body */
<COMMENT>"*/" { BEGIN(comment_caller); }
<INITIAL,BASED_CONST>[ \t\r\n] /* ignore whitespaces */
<INITIAL,BASED_CONST>\\[\r\n] /* ignore continuation sequence */
<INITIAL,BASED_CONST>"//"[^\r\n]* /* ignore one-line comments */
<INITIAL>. { return *yytext; }
<*>. { BEGIN(0); return *yytext; }
<INITIAL>. { return char_tok(*YYText(), out_loc); }
<*>. { 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;
}

View file

@ -0,0 +1,96 @@
#ifndef VERILOG_LOCATION_H
#define VERILOG_LOCATION_H
#include <memory>
#include <string>
#include <stack>
#include <string>
/**
* Provide frontend-wide location tracking like what bison generates
* but using shared_ptr for filename
*/
struct position {
std::shared_ptr<std::string> filename;
int line;
int column;
position(std::shared_ptr<std::string> filename, int line = 1, int column = 1)
: filename(filename), line(line), column(column) {}
position() = default;
position(const position& other) = default;
position& operator=(const position& other) = default;
void advance() { ++column; }
void columns(int count = 1) {
column += count;
}
void lines(int count = 1) {
line += count;
column = 1;
}
std::string to_string() const {
std::ostringstream oss;
if (filename && !filename->empty()) {
oss << *filename << ":";
}
oss << line << ":" << column;
return oss.str();
}
};
struct location {
position begin;
position end;
location() = default;
location(const position& b, const position& e)
: begin(b), end(e) {}
location(const location& other) = default;
location& operator=(const location& other) = default;
void step() { begin = end; }
void columns(int count = 1) {
end.columns(count);
}
void lines(int count = 1) {
end.lines(count);
}
std::string to_string() const {
std::ostringstream oss;
bool same_file = (!begin.filename && !end.filename) ||
(begin.filename && end.filename &&
*begin.filename == *end.filename);
if (same_file) {
if (begin.filename && !begin.filename->empty())
oss << *begin.filename << ":";
if (begin.line == end.line) {
if (begin.column == end.column) {
oss << begin.line << ":" << begin.column;
} else {
oss << begin.line << ":" << begin.column
<< "-" << end.column;
}
} else {
oss << begin.line << ":" << begin.column
<< "-" << end.line << ":" << end.column;
}
} else {
oss << begin.to_string() << "-" << end.to_string();
}
return oss.str();
}
};
static inline std::ostream& operator<<(std::ostream& os, const location& loc) {
return os << loc.to_string();
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -952,10 +952,6 @@ RTLIL::Design::~Design()
delete pr.second;
for (auto n : bindings_)
delete n;
for (auto n : verilog_packages)
delete n;
for (auto n : verilog_globals)
delete n;
#ifdef WITH_PYTHON
RTLIL::Design::get_all_designs()->erase(hashidx_);
#endif
@ -5710,16 +5706,10 @@ static void sigspec_parse_split(std::vector<std::string> &tokens, const std::str
tokens.push_back(text.substr(start));
}
static int sigspec_parse_get_dummy_line_num()
{
return 0;
}
bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::string str)
{
cover("kernel.rtlil.sigspec.parse");
AST::current_filename = "input";
std::vector<std::string> tokens;
sigspec_parse_split(tokens, str, ',');
@ -5735,12 +5725,11 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri
if (('0' <= netname[0] && netname[0] <= '9') || netname[0] == '\'') {
cover("kernel.rtlil.sigspec.parse.const");
AST::get_line_num = sigspec_parse_get_dummy_line_num;
AST::AstNode *ast = VERILOG_FRONTEND::const2ast(netname);
if (ast == NULL)
VERILOG_FRONTEND::ConstParser p{location()};
auto ast = p.const2ast(netname);
if (ast == nullptr)
return false;
sig.append(RTLIL::Const(ast->bits));
delete ast;
continue;
}

View file

@ -1334,7 +1334,7 @@ struct RTLIL::Design
dict<RTLIL::IdString, RTLIL::Module*> modules_;
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::vector<RTLIL::Selection> selection_stack;

View file

@ -20,6 +20,13 @@ mv zlib-1.2.11/* "$vcxsrc"/yosys/libs/zlib/.
rm -rf zlib-1.2.11
pushd "$vcxsrc"/yosys
ls libs/zlib/*.c | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' >> ../../srcfiles.txt
if [ -f "/usr/include/FlexLexer.h" ] ; then
mkdir -p libs/flex
cp /usr/include/FlexLexer.h libs/flex/FlexLexer.h
ls libs/flex/*.h >> ../../srcfiles.txt
fi
popd
{
n=$(grep -B999 '<ItemGroup>' "$vcxsrc"/YosysVS/YosysVS.vcxproj | wc -l)
@ -31,6 +38,9 @@ popd
} > "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
sed -i 's,</AdditionalIncludeDirectories>,</AdditionalIncludeDirectories>\n <LanguageStandard>stdcpp17</LanguageStandard>\n <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions>,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
if [ -f "/usr/include/FlexLexer.h" ] ; then
sed -i 's,</AdditionalIncludeDirectories>,;..\\yosys\\libs\\flex</AdditionalIncludeDirectories>,g' "$vcxsrc"/YosysVS/YosysVS.vcxproj.new
fi
mv "$vcxsrc"/YosysVS/YosysVS.vcxproj.new "$vcxsrc"/YosysVS/YosysVS.vcxproj
mkdir -p "$vcxsrc"/yosys

View file

@ -368,14 +368,8 @@ struct DesignPass : public Pass {
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();
for (auto node : design->verilog_globals)
delete node;
design->verilog_globals.clear();
design->verilog_defines->clear();
}

View file

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