aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md14
-rw-r--r--backends/blif/blif.cc6
-rw-r--r--backends/edif/edif.cc6
-rw-r--r--backends/intersynth/intersynth.cc2
-rw-r--r--backends/smt2/smt2.cc2
-rw-r--r--backends/smv/smv.cc2
-rw-r--r--backends/spice/spice.cc2
-rw-r--r--backends/table/table.cc2
-rw-r--r--backends/verilog/verilog_backend.cc2
-rw-r--r--frontends/ast/ast.cc88
-rw-r--r--frontends/ast/ast.h4
-rw-r--r--frontends/verilog/verilog_frontend.cc23
-rw-r--r--frontends/verilog/verilog_frontend.h6
-rw-r--r--frontends/verilog/verilog_parser.y2
-rw-r--r--kernel/rtlil.cc13
-rw-r--r--kernel/rtlil.h6
-rw-r--r--passes/cmds/add.cc2
-rw-r--r--passes/cmds/bugpoint.cc8
-rw-r--r--passes/cmds/setattr.cc39
-rw-r--r--passes/cmds/show.cc4
-rw-r--r--passes/equiv/equiv_opt.cc2
-rw-r--r--passes/hierarchy/hierarchy.cc10
-rw-r--r--passes/hierarchy/uniquify.cc2
-rw-r--r--passes/proc/proc_mux.cc50
-rw-r--r--passes/proc/proc_rmdead.cc18
-rw-r--r--passes/sat/miter.cc8
-rw-r--r--passes/techmap/dfflibmap.cc2
-rw-r--r--passes/techmap/simplemap.cc2
-rw-r--r--passes/techmap/techmap.cc35
-rwxr-xr-xtests/tools/autotest.sh4
-rw-r--r--tests/various/hierarchy.sh1
31 files changed, 306 insertions, 61 deletions
diff --git a/README.md b/README.md
index d000c5d63..fd45b5470 100644
--- a/README.md
+++ b/README.md
@@ -310,7 +310,19 @@ Verilog Attributes and non-standard features
that have the same ports as the real thing but do not contain information
on the internal configuration. This modules are only used by the synthesis
passes to identify input and output ports of cells. The Verilog backend
- also does not output blackbox modules on default.
+ also does not output blackbox modules on default. ``read_verilog``, unless
+ called with ``-noblackbox`` will automatically set the blackbox attribute
+ on any empty module it reads.
+
+- The ``noblackbox`` attribute set on an empty module prevents ``read_verilog``
+ from automatically setting the blackbox attribute on the module.
+
+- The ``whitebox`` attribute on modules triggers the same behavior as
+ ``blackbox``, but is for whitebox modules, i.e. library modules that
+ contain a behavioral model of the cell type.
+
+- The ``lib_whitebox`` attribute overwrites ``whitebox`` when ``read_verilog``
+ is run in `-lib` mode. Otherwise it's automatically removed.
- The ``dynports`` attribute is used by the Verilog front-end to mark modules
that have ports with a width that depends on a parameter.
diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc
index 0db5ff27c..b6dbd84cb 100644
--- a/backends/blif/blif.cc
+++ b/backends/blif/blif.cc
@@ -140,7 +140,7 @@ struct BlifDumper
return "subckt";
if (!design->modules_.count(RTLIL::escape_id(cell_type)))
return "gate";
- if (design->modules_.at(RTLIL::escape_id(cell_type))->get_bool_attribute("\\blackbox"))
+ if (design->modules_.at(RTLIL::escape_id(cell_type))->get_blackbox_attribute())
return "gate";
return "subckt";
}
@@ -196,7 +196,7 @@ struct BlifDumper
}
f << stringf("\n");
- if (module->get_bool_attribute("\\blackbox")) {
+ if (module->get_blackbox_attribute()) {
f << stringf(".blackbox\n");
f << stringf(".end\n");
return;
@@ -640,7 +640,7 @@ struct BlifBackend : public Backend {
for (auto module_it : design->modules_)
{
RTLIL::Module *module = module_it.second;
- if (module->get_bool_attribute("\\blackbox") && !config.blackbox_mode)
+ if (module->get_blackbox_attribute() && !config.blackbox_mode)
continue;
if (module->processes.size() != 0)
diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc
index 7e30b67af..6d9469538 100644
--- a/backends/edif/edif.cc
+++ b/backends/edif/edif.cc
@@ -178,7 +178,7 @@ struct EdifBackend : public Backend {
for (auto module_it : design->modules_)
{
RTLIL::Module *module = module_it.second;
- if (module->get_bool_attribute("\\blackbox"))
+ if (module->get_blackbox_attribute())
continue;
if (top_module_name.empty())
@@ -192,7 +192,7 @@ struct EdifBackend : public Backend {
for (auto cell_it : module->cells_)
{
RTLIL::Cell *cell = cell_it.second;
- if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) {
+ if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_blackbox_attribute()) {
lib_cell_ports[cell->type];
for (auto p : cell->connections())
lib_cell_ports[cell->type][p.first] = GetSize(p.second);
@@ -302,7 +302,7 @@ struct EdifBackend : public Backend {
*f << stringf(" (technology (numberDefinition))\n");
for (auto module : sorted_modules)
{
- if (module->get_bool_attribute("\\blackbox"))
+ if (module->get_blackbox_attribute())
continue;
SigMap sigmap(module);
diff --git a/backends/intersynth/intersynth.cc b/backends/intersynth/intersynth.cc
index 2eb08dbe9..b0e3cd252 100644
--- a/backends/intersynth/intersynth.cc
+++ b/backends/intersynth/intersynth.cc
@@ -127,7 +127,7 @@ struct IntersynthBackend : public Backend {
RTLIL::Module *module = module_it.second;
SigMap sigmap(module);
- if (module->get_bool_attribute("\\blackbox"))
+ if (module->get_blackbox_attribute())
continue;
if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0)
continue;
diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc
index 688535f33..e318a4051 100644
--- a/backends/smt2/smt2.cc
+++ b/backends/smt2/smt2.cc
@@ -1543,7 +1543,7 @@ struct Smt2Backend : public Backend {
for (auto module : sorted_modules)
{
- if (module->get_bool_attribute("\\blackbox") || module->has_memories_warn() || module->has_processes_warn())
+ if (module->get_blackbox_attribute() || module->has_memories_warn() || module->has_processes_warn())
continue;
log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module));
diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc
index f379c9c48..d75456c1b 100644
--- a/backends/smv/smv.cc
+++ b/backends/smv/smv.cc
@@ -739,7 +739,7 @@ struct SmvBackend : public Backend {
pool<Module*> modules;
for (auto module : design->modules())
- if (!module->get_bool_attribute("\\blackbox") && !module->has_memories_warn() && !module->has_processes_warn())
+ if (!module->get_blackbox_attribute() && !module->has_memories_warn() && !module->has_processes_warn())
modules.insert(module);
if (template_f.is_open())
diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc
index b6a3f1e77..6738a4bbd 100644
--- a/backends/spice/spice.cc
+++ b/backends/spice/spice.cc
@@ -212,7 +212,7 @@ struct SpiceBackend : public Backend {
for (auto module_it : design->modules_)
{
RTLIL::Module *module = module_it.second;
- if (module->get_bool_attribute("\\blackbox"))
+ if (module->get_blackbox_attribute())
continue;
if (module->processes.size() != 0)
diff --git a/backends/table/table.cc b/backends/table/table.cc
index b75169ea4..796f18059 100644
--- a/backends/table/table.cc
+++ b/backends/table/table.cc
@@ -67,7 +67,7 @@ struct TableBackend : public Backend {
for (auto module : design->modules())
{
- if (module->get_bool_attribute("\\blackbox"))
+ if (module->get_blackbox_attribute())
continue;
SigMap sigmap(module);
diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc
index 83d83f488..855409d0b 100644
--- a/backends/verilog/verilog_backend.cc
+++ b/backends/verilog/verilog_backend.cc
@@ -1770,7 +1770,7 @@ struct VerilogBackend : public Backend {
*f << stringf("/* Generated by %s */\n", yosys_version_str);
for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) {
- if (it->second->get_bool_attribute("\\blackbox") != blackboxes)
+ if (it->second->get_blackbox_attribute() != blackboxes)
continue;
if (selected && !design->selected_whole_module(it->first)) {
if (design->selected_module(it->first))
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/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;
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 9ae20a317..f6f08bb9e 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -207,9 +207,12 @@ bool RTLIL::Const::is_fully_undef() const
return true;
}
-void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id)
+void RTLIL::AttrObject::set_bool_attribute(RTLIL::IdString id, bool value)
{
- attributes[id] = RTLIL::Const(1);
+ if (value)
+ attributes[id] = RTLIL::Const(1);
+ else if (attributes.count(id))
+ attributes.erase(id);
}
bool RTLIL::AttrObject::get_bool_attribute(RTLIL::IdString id) const
@@ -589,7 +592,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_modules() const
std::vector<RTLIL::Module*> result;
result.reserve(modules_.size());
for (auto &it : modules_)
- if (selected_module(it.first) && !it.second->get_bool_attribute("\\blackbox"))
+ if (selected_module(it.first) && !it.second->get_blackbox_attribute())
result.push_back(it.second);
return result;
}
@@ -599,7 +602,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules() const
std::vector<RTLIL::Module*> result;
result.reserve(modules_.size());
for (auto &it : modules_)
- if (selected_whole_module(it.first) && !it.second->get_bool_attribute("\\blackbox"))
+ if (selected_whole_module(it.first) && !it.second->get_blackbox_attribute())
result.push_back(it.second);
return result;
}
@@ -609,7 +612,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules_warn() const
std::vector<RTLIL::Module*> result;
result.reserve(modules_.size());
for (auto &it : modules_)
- if (it.second->get_bool_attribute("\\blackbox"))
+ if (it.second->get_blackbox_attribute())
continue;
else if (selected_whole_module(it.first))
result.push_back(it.second);
diff --git a/kernel/rtlil.h b/kernel/rtlil.h
index fb045bc72..330a81c3b 100644
--- a/kernel/rtlil.h
+++ b/kernel/rtlil.h
@@ -566,9 +566,13 @@ struct RTLIL::AttrObject
{
dict<RTLIL::IdString, RTLIL::Const> attributes;
- void set_bool_attribute(RTLIL::IdString id);
+ void set_bool_attribute(RTLIL::IdString id, bool value=true);
bool get_bool_attribute(RTLIL::IdString id) const;
+ bool get_blackbox_attribute(bool ignore_wb=false) const {
+ return get_bool_attribute("\\blackbox") || (!ignore_wb && get_bool_attribute("\\whitebox"));
+ }
+
void set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
void add_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
pool<string> get_strpool_attribute(RTLIL::IdString id) const;
diff --git a/passes/cmds/add.cc b/passes/cmds/add.cc
index cfccca966..af6f7043d 100644
--- a/passes/cmds/add.cc
+++ b/passes/cmds/add.cc
@@ -71,7 +71,7 @@ static void add_wire(RTLIL::Design *design, RTLIL::Module *module, std::string n
RTLIL::Module *mod = design->modules_.at(it.second->type);
if (!design->selected_whole_module(mod->name))
continue;
- if (mod->get_bool_attribute("\\blackbox"))
+ if (mod->get_blackbox_attribute())
continue;
if (it.second->hasPort(name))
continue;
diff --git a/passes/cmds/bugpoint.cc b/passes/cmds/bugpoint.cc
index 606276e64..4b22f6d2d 100644
--- a/passes/cmds/bugpoint.cc
+++ b/passes/cmds/bugpoint.cc
@@ -128,7 +128,7 @@ struct BugpointPass : public Pass {
{
for (auto &it : design_copy->modules_)
{
- if (it.second->get_bool_attribute("\\blackbox"))
+ if (it.second->get_blackbox_attribute())
continue;
if (index++ == seed)
@@ -143,7 +143,7 @@ struct BugpointPass : public Pass {
{
for (auto mod : design_copy->modules())
{
- if (mod->get_bool_attribute("\\blackbox"))
+ if (mod->get_blackbox_attribute())
continue;
for (auto wire : mod->wires())
@@ -168,7 +168,7 @@ struct BugpointPass : public Pass {
{
for (auto mod : design_copy->modules())
{
- if (mod->get_bool_attribute("\\blackbox"))
+ if (mod->get_blackbox_attribute())
continue;
for (auto &it : mod->cells_)
@@ -186,7 +186,7 @@ struct BugpointPass : public Pass {
{
for (auto mod : design_copy->modules())
{
- if (mod->get_bool_attribute("\\blackbox"))
+ if (mod->get_blackbox_attribute())
continue;
for (auto cell : mod->cells())
diff --git a/passes/cmds/setattr.cc b/passes/cmds/setattr.cc
index d38a6b3da..b9fcc3e7a 100644
--- a/passes/cmds/setattr.cc
+++ b/passes/cmds/setattr.cc
@@ -128,6 +128,45 @@ struct SetattrPass : public Pass {
}
} SetattrPass;
+struct WbflipPass : public Pass {
+ WbflipPass() : Pass("wbflip", "flip the whitebox attribute") { }
+ void help() YS_OVERRIDE
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" wbflip [selection]\n");
+ log("\n");
+ log("Flip the whitebox attribute on selected cells. I.e. if it's set, unset it, and\n");
+ log("vice-versa. Blackbox cells are not effected by this command.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
+ {
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ std::string arg = args[argidx];
+ // if (arg == "-mod") {
+ // flag_mod = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (Module *module : design->modules())
+ {
+ if (!design->selected(module))
+ continue;
+
+ if (module->get_bool_attribute("\\blackbox"))
+ continue;
+
+ module->set_bool_attribute("\\whitebox", !module->get_bool_attribute("\\whitebox"));
+ }
+ }
+} WbflipPass;
+
struct SetparamPass : public Pass {
SetparamPass() : Pass("setparam", "set/unset parameters on objects") { }
void help() YS_OVERRIDE
diff --git a/passes/cmds/show.cc b/passes/cmds/show.cc
index 0eadd904a..cf729215f 100644
--- a/passes/cmds/show.cc
+++ b/passes/cmds/show.cc
@@ -574,7 +574,7 @@ struct ShowWorker
if (!design->selected_module(module->name))
continue;
if (design->selected_whole_module(module->name)) {
- if (module->get_bool_attribute("\\blackbox")) {
+ if (module->get_blackbox_attribute()) {
// log("Skipping blackbox module %s.\n", id2cstr(module->name));
continue;
} else
@@ -790,7 +790,7 @@ struct ShowPass : public Pass {
if (format != "ps" && format != "dot") {
int modcount = 0;
for (auto &mod_it : design->modules_) {
- if (mod_it.second->get_bool_attribute("\\blackbox"))
+ if (mod_it.second->get_blackbox_attribute())
continue;
if (mod_it.second->cells_.empty() && mod_it.second->connections().empty())
continue;
diff --git a/passes/equiv/equiv_opt.cc b/passes/equiv/equiv_opt.cc
index 86550a69b..e5dda9c24 100644
--- a/passes/equiv/equiv_opt.cc
+++ b/passes/equiv/equiv_opt.cc
@@ -134,7 +134,7 @@ struct EquivOptPass:public ScriptPass
opts = " -map <filename> ...";
else
opts = techmap_opts;
- run("techmap -D EQUIV -autoproc" + opts);
+ run("techmap -wb -D EQUIV -autoproc" + opts);
}
if (check_label("prove")) {
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc
index 88c339e8c..b8ff99884 100644
--- a/passes/hierarchy/hierarchy.cc
+++ b/passes/hierarchy/hierarchy.cc
@@ -346,9 +346,9 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
}
RTLIL::Module *mod = design->modules_[cell->type];
- if (design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) {
+ if (design->modules_.at(cell->type)->get_blackbox_attribute()) {
if (flag_simcheck)
- log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox module.\n",
+ log_error("Module `%s' referenced in module `%s' in cell `%s' is a blackbox/whitebox module.\n",
cell->type.c_str(), module->name.c_str(), cell->name.c_str());
continue;
}
@@ -451,7 +451,7 @@ void hierarchy_worker(RTLIL::Design *design, std::set<RTLIL::Module*, IdString::
if (indent == 0)
log("Top module: %s\n", mod->name.c_str());
- else if (!mod->get_bool_attribute("\\blackbox"))
+ else if (!mod->get_blackbox_attribute())
log("Used module: %*s%s\n", indent, "", mod->name.c_str());
used.insert(mod);
@@ -491,7 +491,7 @@ void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib)
int del_counter = 0;
for (auto mod : del_modules) {
- if (!purge_lib && mod->get_bool_attribute("\\blackbox"))
+ if (!purge_lib && mod->get_blackbox_attribute())
continue;
log("Removing unused module `%s'.\n", mod->name.c_str());
design->modules_.erase(mod->name);
@@ -910,7 +910,7 @@ struct HierarchyPass : public Pass {
if (m == nullptr)
continue;
- if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
+ if (m->get_blackbox_attribute() && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) {
IdString new_m_name = m->derive(design, cell->parameters, true);
if (new_m_name.empty())
continue;
diff --git a/passes/hierarchy/uniquify.cc b/passes/hierarchy/uniquify.cc
index e6154e94f..ad3220918 100644
--- a/passes/hierarchy/uniquify.cc
+++ b/passes/hierarchy/uniquify.cc
@@ -75,7 +75,7 @@ struct UniquifyPass : public Pass {
if (tmod == nullptr)
continue;
- if (tmod->get_bool_attribute("\\blackbox"))
+ if (tmod->get_blackbox_attribute())
continue;
if (tmod->get_bool_attribute("\\unique") && newname == tmod->name)
diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc
index 1329c1fef..aac0b121c 100644
--- a/passes/proc/proc_mux.cc
+++ b/passes/proc/proc_mux.cc
@@ -108,6 +108,7 @@ struct SigSnippets
struct SnippetSwCache
{
+ dict<RTLIL::SwitchRule*, pool<RTLIL::SigBit>, hash_ptr_ops> full_case_bits_cache;
dict<RTLIL::SwitchRule*, pool<int>, hash_ptr_ops> cache;
const SigSnippets *snippets;
int current_snippet;
@@ -268,6 +269,49 @@ void append_pmux(RTLIL::Module *mod, const RTLIL::SigSpec &signal, const std::ve
last_mux_cell->parameters["\\S_WIDTH"] = last_mux_cell->getPort("\\S").size();
}
+const pool<SigBit> &get_full_case_bits(SnippetSwCache &swcache, RTLIL::SwitchRule *sw)
+{
+ if (!swcache.full_case_bits_cache.count(sw))
+ {
+ pool<SigBit> bits;
+
+ if (sw->get_bool_attribute("\\full_case"))
+ {
+ bool first_case = true;
+
+ for (auto cs : sw->cases)
+ {
+ pool<SigBit> case_bits;
+
+ for (auto it : cs->actions) {
+ for (auto bit : it.first)
+ case_bits.insert(bit);
+ }
+
+ for (auto it : cs->switches) {
+ for (auto bit : get_full_case_bits(swcache, it))
+ case_bits.insert(bit);
+ }
+
+ if (first_case) {
+ first_case = false;
+ bits = case_bits;
+ } else {
+ pool<SigBit> new_bits;
+ for (auto bit : bits)
+ if (case_bits.count(bit))
+ new_bits.insert(bit);
+ bits.swap(new_bits);
+ }
+ }
+ }
+
+ bits.swap(swcache.full_case_bits_cache[sw]);
+ }
+
+ return swcache.full_case_bits_cache.at(sw);
+}
+
RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, dict<RTLIL::SwitchRule*, bool, hash_ptr_ops> &swpara,
RTLIL::CaseRule *cs, const RTLIL::SigSpec &sig, const RTLIL::SigSpec &defval, bool ifxmode)
{
@@ -337,6 +381,12 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
}
}
+ // mask default bits that are irrelevant because the output is driven by a full case
+ const pool<SigBit> &full_case_bits = get_full_case_bits(swcache, sw);
+ for (int i = 0; i < GetSize(sig); i++)
+ if (full_case_bits.count(sig[i]))
+ result[i] = State::Sx;
+
// evaluate in reverse order to give the first entry the top priority
RTLIL::SigSpec initial_val = result;
RTLIL::Cell *last_mux_cell = NULL;
diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc
index 7c334e661..4f40be446 100644
--- a/passes/proc/proc_rmdead.cc
+++ b/passes/proc/proc_rmdead.cc
@@ -28,7 +28,7 @@
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
-void proc_rmdead(RTLIL::SwitchRule *sw, int &counter)
+void proc_rmdead(RTLIL::SwitchRule *sw, int &counter, int &full_case_counter)
{
BitPatternPool pool(sw->signal);
@@ -56,11 +56,16 @@ void proc_rmdead(RTLIL::SwitchRule *sw, int &counter)
}
for (auto switch_it : sw->cases[i]->switches)
- proc_rmdead(switch_it, counter);
+ proc_rmdead(switch_it, counter, full_case_counter);
if (is_default)
pool.take_all();
}
+
+ if (pool.empty() && !sw->get_bool_attribute("\\full_case")) {
+ sw->set_bool_attribute("\\full_case");
+ full_case_counter++;
+ }
}
struct ProcRmdeadPass : public Pass {
@@ -87,12 +92,15 @@ struct ProcRmdeadPass : public Pass {
for (auto &proc_it : mod->processes) {
if (!design->selected(mod, proc_it.second))
continue;
- int counter = 0;
+ int counter = 0, full_case_counter = 0;
for (auto switch_it : proc_it.second->root_case.switches)
- proc_rmdead(switch_it, counter);
+ proc_rmdead(switch_it, counter, full_case_counter);
if (counter > 0)
log("Removed %d dead cases from process %s in module %s.\n", counter,
- proc_it.first.c_str(), log_id(mod));
+ log_id(proc_it.first), log_id(mod));
+ if (full_case_counter > 0)
+ log("Marked %d switch rules as full_case in process %s in module %s.\n",
+ full_case_counter, log_id(proc_it.first), log_id(mod));
total_counter += counter;
}
}
diff --git a/passes/sat/miter.cc b/passes/sat/miter.cc
index d37f1b126..1a886af70 100644
--- a/passes/sat/miter.cc
+++ b/passes/sat/miter.cc
@@ -254,7 +254,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
if (flag_flatten) {
log_push();
- Pass::call_on_module(design, miter_module, "flatten; opt_expr -keepdc -undriven;;");
+ Pass::call_on_module(design, miter_module, "flatten -wb; opt_expr -keepdc -undriven;;");
log_pop();
}
}
@@ -308,7 +308,7 @@ void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL
if (flag_flatten) {
log_push();
- Pass::call_on_module(design, module, "flatten;;");
+ Pass::call_on_module(design, module, "flatten -wb;;");
log_pop();
}
@@ -385,7 +385,7 @@ struct MiterPass : public Pass {
log(" also create an 'assert' cell that checks if trigger is always low.\n");
log("\n");
log(" -flatten\n");
- log(" call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
+ log(" call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
log("\n");
log("\n");
log(" miter -assert [options] module [miter_name]\n");
@@ -399,7 +399,7 @@ struct MiterPass : public Pass {
log(" keep module output ports.\n");
log("\n");
log(" -flatten\n");
- log(" call 'flatten; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
+ log(" call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 274177a68..b5c0498d0 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -664,7 +664,7 @@ struct DfflibmapPass : public Pass {
logmap_all();
for (auto &it : design->modules_)
- if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox"))
+ if (design->selected(it.second) && !it.second->get_blackbox_attribute())
dfflibmap(design, it.second, prepare_mode);
cell_mappings.clear();
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index 660b60601..f3da80c66 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -599,7 +599,7 @@ struct SimplemapPass : public Pass {
simplemap_get_mappers(mappers);
for (auto mod : design->modules()) {
- if (!design->selected(mod))
+ if (!design->selected(mod) || mod->get_blackbox_attribute())
continue;
std::vector<RTLIL::Cell*> cells = mod->cells();
for (auto cell : cells) {
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index d0e5e2236..1a4318460 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -84,6 +84,7 @@ struct TechmapWorker
bool flatten_mode;
bool recursive_mode;
bool autoproc_mode;
+ bool ignore_wb;
TechmapWorker()
{
@@ -92,6 +93,7 @@ struct TechmapWorker
flatten_mode = false;
recursive_mode = false;
autoproc_mode = false;
+ ignore_wb = false;
}
std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose)
@@ -383,7 +385,7 @@ struct TechmapWorker
{
std::string mapmsg_prefix = in_recursion ? "Recursively mapping" : "Mapping";
- if (!design->selected(module))
+ if (!design->selected(module) || module->get_blackbox_attribute(ignore_wb))
return false;
bool log_continue = false;
@@ -472,7 +474,7 @@ struct TechmapWorker
RTLIL::Module *tpl = map->modules_[tpl_name];
std::map<RTLIL::IdString, RTLIL::Const> parameters(cell->parameters.begin(), cell->parameters.end());
- if (tpl->get_bool_attribute("\\blackbox"))
+ if (tpl->get_blackbox_attribute(ignore_wb))
continue;
if (!flatten_mode)
@@ -925,6 +927,9 @@ struct TechmapPass : public Pass {
log(" -autoproc\n");
log(" Automatically call \"proc\" on implementations that contain processes.\n");
log("\n");
+ log(" -wb\n");
+ log(" Ignore the 'whitebox' attribute on cell implementations.\n");
+ log("\n");
log(" -assert\n");
log(" this option will cause techmap to exit with an error if it can't map\n");
log(" a selected cell. only cell types that end on an underscore are accepted\n");
@@ -1031,7 +1036,7 @@ struct TechmapPass : public Pass {
simplemap_get_mappers(worker.simplemap_mappers);
std::vector<std::string> map_files;
- std::string verilog_frontend = "verilog -nooverwrite";
+ std::string verilog_frontend = "verilog -nooverwrite -noblackbox";
int max_iter = -1;
size_t argidx;
@@ -1068,6 +1073,10 @@ struct TechmapPass : public Pass {
worker.autoproc_mode = true;
continue;
}
+ if (args[argidx] == "-wb") {
+ worker.ignore_wb = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -1145,7 +1154,7 @@ struct FlattenPass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" flatten [selection]\n");
+ log(" flatten [options] [selection]\n");
log("\n");
log("This pass flattens the design by replacing cells by their implementation. This\n");
log("pass is very similar to the 'techmap' pass. The only difference is that this\n");
@@ -1154,17 +1163,29 @@ struct FlattenPass : public Pass {
log("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n");
log("flattened by this command.\n");
log("\n");
+ log(" -wb\n");
+ log(" Ignore the 'whitebox' attribute on cell implementations.\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
log_header(design, "Executing FLATTEN pass (flatten design).\n");
log_push();
- extra_args(args, 1, design);
-
TechmapWorker worker;
worker.flatten_mode = true;
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-wb") {
+ worker.ignore_wb = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+
std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
for (auto module : design->modules())
celltypeMap[module->name].insert(module->name);
@@ -1209,7 +1230,7 @@ struct FlattenPass : public Pass {
dict<RTLIL::IdString, RTLIL::Module*> new_modules;
for (auto mod : vector<Module*>(design->modules()))
- if (used_modules[mod->name] || mod->get_bool_attribute("\\blackbox")) {
+ if (used_modules[mod->name] || mod->get_blackbox_attribute(worker.ignore_wb)) {
new_modules[mod->name] = mod;
} else {
log("Deleting now unused module %s.\n", log_id(mod));
diff --git a/tests/tools/autotest.sh b/tests/tools/autotest.sh
index f3dac504e..bb9c3bfb5 100755
--- a/tests/tools/autotest.sh
+++ b/tests/tools/autotest.sh
@@ -7,7 +7,7 @@ use_modelsim=false
verbose=false
keeprunning=false
makejmode=false
-frontend="verilog"
+frontend="verilog -noblackbox"
backend_opts="-noattr -noexpr -siminit"
autotb_opts=""
include_opts=""
@@ -137,7 +137,7 @@ do
egrep -v '^\s*`timescale' ../$fn > ${bn}_ref.${ext}
else
"$toolsdir"/../../yosys -f "$frontend $include_opts" -b "verilog" -o ${bn}_ref.v ../${fn}
- frontend="verilog"
+ frontend="verilog -noblackbox"
fi
if [ ! -f ../${bn}_tb.v ]; then
diff --git a/tests/various/hierarchy.sh b/tests/various/hierarchy.sh
index d33a247be..9dbd1c89f 100644
--- a/tests/various/hierarchy.sh
+++ b/tests/various/hierarchy.sh
@@ -53,6 +53,7 @@ echo -n " no explicit top - "
module noTop(a, y);
input a;
output [31:0] y;
+ assign y = a;
endmodule
EOV
hierarchy -auto-top