aboutsummaryrefslogtreecommitdiffstats
path: root/frontends
diff options
context:
space:
mode:
Diffstat (limited to 'frontends')
-rw-r--r--frontends/ast/ast.cc88
-rw-r--r--frontends/ast/ast.h4
-rw-r--r--frontends/ast/simplify.cc21
-rw-r--r--frontends/verilog/verilog_frontend.cc23
-rw-r--r--frontends/verilog/verilog_frontend.h6
-rw-r--r--frontends/verilog/verilog_parser.y2
6 files changed, 135 insertions, 9 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index d48996167..9f88b08c1 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -46,7 +46,7 @@ namespace AST {
// instantiate global variables (private API)
namespace AST_INTERNAL {
bool flag_dump_ast1, flag_dump_ast2, flag_no_dump_ptr, flag_dump_vlog1, flag_dump_vlog2, flag_dump_rtlil, flag_nolatches, flag_nomeminit;
- bool flag_nomem2reg, flag_mem2reg, flag_lib, flag_noopt, flag_icells, flag_autowire;
+ bool flag_nomem2reg, flag_mem2reg, flag_noblackbox, flag_lib, flag_nowb, flag_noopt, flag_icells, flag_autowire;
AstNode *current_ast, *current_ast_mod;
std::map<std::string, AstNode*> current_scope;
const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL;
@@ -942,6 +942,20 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
if (!defer)
{
+ bool blackbox_module = flag_lib;
+
+ if (!blackbox_module && !flag_noblackbox) {
+ blackbox_module = true;
+ for (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)
+ continue;
+ blackbox_module = false;
+ break;
+ }
+ }
+
while (ast->simplify(!flag_noopt, false, false, 0, -1, false, false)) { }
if (flag_dump_ast2) {
@@ -956,7 +970,63 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
log("--- END OF AST DUMP ---\n");
}
- if (flag_lib) {
+ if (flag_nowb && ast->attributes.count("\\whitebox")) {
+ delete ast->attributes.at("\\whitebox");
+ ast->attributes.erase("\\whitebox");
+ }
+
+ if (ast->attributes.count("\\lib_whitebox")) {
+ if (!flag_lib || flag_nowb) {
+ delete ast->attributes.at("\\lib_whitebox");
+ ast->attributes.erase("\\lib_whitebox");
+ } else {
+ if (ast->attributes.count("\\whitebox")) {
+ delete ast->attributes.at("\\whitebox");
+ ast->attributes.erase("\\whitebox");
+ }
+ AstNode *n = ast->attributes.at("\\lib_whitebox");
+ ast->attributes["\\whitebox"] = n;
+ ast->attributes.erase("\\lib_whitebox");
+ }
+ }
+
+ if (!blackbox_module && ast->attributes.count("\\blackbox")) {
+ AstNode *n = ast->attributes.at("\\blackbox");
+ if (n->type != AST_CONSTANT)
+ log_file_error(ast->filename, ast->linenum, "Got blackbox attribute with non-constant value!\n");
+ blackbox_module = n->asBool();
+ }
+
+ if (blackbox_module && ast->attributes.count("\\whitebox")) {
+ AstNode *n = ast->attributes.at("\\whitebox");
+ if (n->type != AST_CONSTANT)
+ log_file_error(ast->filename, ast->linenum, "Got whitebox attribute with non-constant value!\n");
+ blackbox_module = !n->asBool();
+ }
+
+ if (ast->attributes.count("\\noblackbox")) {
+ if (blackbox_module) {
+ AstNode *n = ast->attributes.at("\\noblackbox");
+ if (n->type != AST_CONSTANT)
+ log_file_error(ast->filename, ast->linenum, "Got noblackbox attribute with non-constant value!\n");
+ blackbox_module = !n->asBool();
+ }
+ delete ast->attributes.at("\\noblackbox");
+ ast->attributes.erase("\\noblackbox");
+ }
+
+ if (blackbox_module)
+ {
+ if (ast->attributes.count("\\whitebox")) {
+ delete ast->attributes.at("\\whitebox");
+ ast->attributes.erase("\\whitebox");
+ }
+
+ if (ast->attributes.count("\\lib_whitebox")) {
+ delete ast->attributes.at("\\lib_whitebox");
+ ast->attributes.erase("\\lib_whitebox");
+ }
+
std::vector<AstNode*> new_children;
for (auto child : ast->children) {
if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
@@ -969,8 +1039,12 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
delete child;
}
}
+
ast->children.swap(new_children);
- ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false);
+
+ if (ast->attributes.count("\\blackbox") == 0) {
+ ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false);
+ }
}
ignoreThisSignalsInInitial = RTLIL::SigSpec();
@@ -1009,7 +1083,9 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
current_module->nomeminit = flag_nomeminit;
current_module->nomem2reg = flag_nomem2reg;
current_module->mem2reg = flag_mem2reg;
+ current_module->noblackbox = flag_noblackbox;
current_module->lib = flag_lib;
+ current_module->nowb = flag_nowb;
current_module->noopt = flag_noopt;
current_module->icells = flag_icells;
current_module->autowire = flag_autowire;
@@ -1026,7 +1102,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
// create AstModule instances for all modules in the AST tree and add them to 'design'
void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil,
- bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire)
+ bool nolatches, bool nomeminit, bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire)
{
current_ast = ast;
flag_dump_ast1 = dump_ast1;
@@ -1039,7 +1115,9 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
flag_nomeminit = nomeminit;
flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg;
+ flag_noblackbox = noblackbox;
flag_lib = lib;
+ flag_nowb = nowb;
flag_noopt = noopt;
flag_icells = icells;
flag_autowire = autowire;
@@ -1373,7 +1451,9 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
flag_nomeminit = nomeminit;
flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg;
+ flag_noblackbox = noblackbox;
flag_lib = lib;
+ flag_nowb = nowb;
flag_noopt = noopt;
flag_icells = icells;
flag_autowire = autowire;
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index ddd59d4be..281cbe086 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -283,13 +283,13 @@ namespace AST
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
void process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump_ast2, bool no_dump_ptr, bool dump_vlog1, bool dump_vlog2, bool dump_rtlil, bool nolatches, bool nomeminit,
- bool nomem2reg, bool mem2reg, bool lib, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire);
+ bool nomem2reg, bool mem2reg, bool noblackbox, bool lib, bool nowb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire);
// 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;
- bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire;
+ bool nolatches, nomeminit, nomem2reg, mem2reg, noblackbox, lib, nowb, noopt, icells, autowire;
~AstModule() YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool mayfail) YS_OVERRIDE;
RTLIL::IdString derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, dict<RTLIL::IdString, RTLIL::Module*> interfaces, dict<RTLIL::IdString, RTLIL::IdString> modports, bool mayfail) YS_OVERRIDE;
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 63b71b800..76da5a97c 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -1030,7 +1030,26 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
log_file_error(filename, linenum, "While loops are only allowed in constant functions!\n");
if (type == AST_REPEAT)
- log_file_error(filename, linenum, "Repeat loops are only allowed in constant functions!\n");
+ {
+ AstNode *count = children[0];
+ AstNode *body = children[1];
+
+ // eval count expression
+ while (count->simplify(true, false, false, stage, 32, true, false)) { }
+
+ if (count->type != AST_CONSTANT)
+ log_file_error(filename, linenum, "Repeat loops outside must have constant repeat counts!\n");
+
+ // convert to a block with the body repeated n times
+ type = AST_BLOCK;
+ children.clear();
+ for (int i = 0; i < count->bitsAsConst().as_int(); i++)
+ children.insert(children.begin(), body->clone());
+
+ delete count;
+ delete body;
+ did_something = true;
+ }
// unroll for loops and generate-for blocks
if ((type == AST_GENFOR || type == AST_FOR) && children.size() != 0)
diff --git a/frontends/verilog/verilog_frontend.cc b/frontends/verilog/verilog_frontend.cc
index 504f8b3f3..ed6ce2ecb 100644
--- a/frontends/verilog/verilog_frontend.cc
+++ b/frontends/verilog/verilog_frontend.cc
@@ -145,8 +145,18 @@ struct VerilogFrontend : public Frontend {
log(" -nodpi\n");
log(" disable DPI-C support\n");
log("\n");
+ log(" -noblackbox\n");
+ log(" do not automatically add a (* blackbox *) attribute to an\n");
+ log(" empty module.\n");
+ log("\n");
log(" -lib\n");
log(" only create empty blackbox modules. This implies -DBLACKBOX.\n");
+ log(" modules with the (* whitebox *) attribute will be preserved.\n");
+ log(" (* lib_whitebox *) will be treated like (* whitebox *).\n");
+ log("\n");
+ log(" -nowb\n");
+ log(" delete (* whitebox *) and (* lib_whitebox *) attributes from\n");
+ log(" all modules.\n");
log("\n");
log(" -noopt\n");
log(" don't perform basic optimizations (such as const folding) in the\n");
@@ -227,7 +237,9 @@ struct VerilogFrontend : public Frontend {
formal_mode = false;
norestrict_mode = false;
assume_asserts_mode = false;
+ noblackbox_mode = false;
lib_mode = false;
+ nowb_mode = false;
default_nettype_wire = true;
log_header(design, "Executing Verilog-2005 frontend.\n");
@@ -329,11 +341,19 @@ struct VerilogFrontend : public Frontend {
flag_nodpi = true;
continue;
}
+ if (arg == "-noblackbox") {
+ noblackbox_mode = true;
+ continue;
+ }
if (arg == "-lib") {
lib_mode = true;
defines_map["BLACKBOX"] = string();
continue;
}
+ if (arg == "-nowb") {
+ nowb_mode = true;
+ continue;
+ }
if (arg == "-noopt") {
flag_noopt = true;
continue;
@@ -429,7 +449,8 @@ struct VerilogFrontend : public Frontend {
if (flag_nodpi)
error_on_dpi_function(current_ast);
- AST::process(design, current_ast, 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, lib_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
+ AST::process(design, current_ast, 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, noblackbox_mode, lib_mode, nowb_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
if (!flag_nopp)
delete lexin;
diff --git a/frontends/verilog/verilog_frontend.h b/frontends/verilog/verilog_frontend.h
index 523bbc897..ca40946cb 100644
--- a/frontends/verilog/verilog_frontend.h
+++ b/frontends/verilog/verilog_frontend.h
@@ -69,9 +69,15 @@ namespace VERILOG_FRONTEND
// running in -assert-assumes mode
extern bool assert_assumes_mode;
+ // running in -noblackbox mode
+ extern bool noblackbox_mode;
+
// running in -lib mode
extern bool lib_mode;
+ // running in -nowb mode
+ extern bool nowb_mode;
+
// lexer input stream
extern std::istream *lexin;
}
diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y
index 52685f637..40968d17a 100644
--- a/frontends/verilog/verilog_parser.y
+++ b/frontends/verilog/verilog_parser.y
@@ -59,7 +59,7 @@ namespace VERILOG_FRONTEND {
std::vector<char> case_type_stack;
bool do_not_require_port_stubs;
bool default_nettype_wire;
- bool sv_mode, formal_mode, lib_mode;
+ bool sv_mode, formal_mode, noblackbox_mode, lib_mode, nowb_mode;
bool noassert_mode, noassume_mode, norestrict_mode;
bool assume_asserts_mode, assert_assumes_mode;
bool current_wire_rand, current_wire_const;