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

Merge pull request #943 from YosysHQ/clifford/whitebox

[WIP] Add "whitebox" attribute, add "read_verilog -wb"
This commit is contained in:
Clifford Wolf 2019-04-20 20:51:54 +02:00 committed by GitHub
commit f84a84e3f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 157 additions and 55 deletions

View file

@ -312,6 +312,10 @@ Verilog Attributes and non-standard features
passes to identify input and output ports of cells. The Verilog backend 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.
- 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 ``dynports`` attribute is used by the Verilog front-end to mark modules - The ``dynports`` attribute is used by the Verilog front-end to mark modules
that have ports with a width that depends on a parameter. that have ports with a width that depends on a parameter.

View file

@ -140,7 +140,7 @@ struct BlifDumper
return "subckt"; return "subckt";
if (!design->modules_.count(RTLIL::escape_id(cell_type))) if (!design->modules_.count(RTLIL::escape_id(cell_type)))
return "gate"; 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 "gate";
return "subckt"; return "subckt";
} }
@ -196,7 +196,7 @@ struct BlifDumper
} }
f << stringf("\n"); f << stringf("\n");
if (module->get_bool_attribute("\\blackbox")) { if (module->get_blackbox_attribute()) {
f << stringf(".blackbox\n"); f << stringf(".blackbox\n");
f << stringf(".end\n"); f << stringf(".end\n");
return; return;
@ -640,7 +640,7 @@ struct BlifBackend : public Backend {
for (auto module_it : design->modules_) for (auto module_it : design->modules_)
{ {
RTLIL::Module *module = module_it.second; RTLIL::Module *module = module_it.second;
if (module->get_bool_attribute("\\blackbox") && !config.blackbox_mode) if (module->get_blackbox_attribute() && !config.blackbox_mode)
continue; continue;
if (module->processes.size() != 0) if (module->processes.size() != 0)

View file

@ -178,7 +178,7 @@ struct EdifBackend : public Backend {
for (auto module_it : design->modules_) for (auto module_it : design->modules_)
{ {
RTLIL::Module *module = module_it.second; RTLIL::Module *module = module_it.second;
if (module->get_bool_attribute("\\blackbox")) if (module->get_blackbox_attribute())
continue; continue;
if (top_module_name.empty()) if (top_module_name.empty())
@ -192,7 +192,7 @@ struct EdifBackend : public Backend {
for (auto cell_it : module->cells_) for (auto cell_it : module->cells_)
{ {
RTLIL::Cell *cell = cell_it.second; 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]; lib_cell_ports[cell->type];
for (auto p : cell->connections()) for (auto p : cell->connections())
lib_cell_ports[cell->type][p.first] = GetSize(p.second); lib_cell_ports[cell->type][p.first] = GetSize(p.second);
@ -302,7 +302,7 @@ struct EdifBackend : public Backend {
*f << stringf(" (technology (numberDefinition))\n"); *f << stringf(" (technology (numberDefinition))\n");
for (auto module : sorted_modules) for (auto module : sorted_modules)
{ {
if (module->get_bool_attribute("\\blackbox")) if (module->get_blackbox_attribute())
continue; continue;
SigMap sigmap(module); SigMap sigmap(module);

View file

@ -127,7 +127,7 @@ struct IntersynthBackend : public Backend {
RTLIL::Module *module = module_it.second; RTLIL::Module *module = module_it.second;
SigMap sigmap(module); SigMap sigmap(module);
if (module->get_bool_attribute("\\blackbox")) if (module->get_blackbox_attribute())
continue; continue;
if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0) if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0)
continue; continue;

View file

@ -1543,7 +1543,7 @@ struct Smt2Backend : public Backend {
for (auto module : sorted_modules) 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; continue;
log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module)); log("Creating SMT-LIBv2 representation of module %s.\n", log_id(module));

View file

@ -739,7 +739,7 @@ struct SmvBackend : public Backend {
pool<Module*> modules; pool<Module*> modules;
for (auto module : design->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); modules.insert(module);
if (template_f.is_open()) if (template_f.is_open())

View file

@ -212,7 +212,7 @@ struct SpiceBackend : public Backend {
for (auto module_it : design->modules_) for (auto module_it : design->modules_)
{ {
RTLIL::Module *module = module_it.second; RTLIL::Module *module = module_it.second;
if (module->get_bool_attribute("\\blackbox")) if (module->get_blackbox_attribute())
continue; continue;
if (module->processes.size() != 0) if (module->processes.size() != 0)

View file

@ -67,7 +67,7 @@ struct TableBackend : public Backend {
for (auto module : design->modules()) for (auto module : design->modules())
{ {
if (module->get_bool_attribute("\\blackbox")) if (module->get_blackbox_attribute())
continue; continue;
SigMap sigmap(module); SigMap sigmap(module);

View file

@ -1770,7 +1770,7 @@ struct VerilogBackend : public Backend {
*f << stringf("/* Generated by %s */\n", yosys_version_str); *f << stringf("/* Generated by %s */\n", yosys_version_str);
for (auto it = design->modules_.begin(); it != design->modules_.end(); ++it) { 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; continue;
if (selected && !design->selected_whole_module(it->first)) { if (selected && !design->selected_whole_module(it->first)) {
if (design->selected_module(it->first)) if (design->selected_module(it->first))

View file

@ -46,7 +46,7 @@ namespace AST {
// instantiate global variables (private API) // instantiate global variables (private API)
namespace AST_INTERNAL { 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_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_lib, flag_wb, flag_noopt, flag_icells, flag_autowire;
AstNode *current_ast, *current_ast_mod; AstNode *current_ast, *current_ast_mod;
std::map<std::string, AstNode*> current_scope; std::map<std::string, AstNode*> current_scope;
const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL; const dict<RTLIL::SigBit, RTLIL::SigBit> *genRTLIL_subst_ptr = NULL;
@ -956,7 +956,18 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
log("--- END OF AST DUMP ---\n"); log("--- END OF AST DUMP ---\n");
} }
if (flag_wb) {
if (!ast->attributes.count("\\whitebox"))
goto blackbox_module;
AstNode *n = ast->attributes.at("\\whitebox");
if (n->type != AST_CONSTANT)
log_file_error(ast->filename, ast->linenum, "Whitebox attribute with non-constant value!\n");
if (!n->asBool())
goto blackbox_module;
}
if (flag_lib) { if (flag_lib) {
blackbox_module:
std::vector<AstNode*> new_children; std::vector<AstNode*> new_children;
for (auto child : ast->children) { for (auto child : ast->children) {
if (child->type == AST_WIRE && (child->is_input || child->is_output)) { if (child->type == AST_WIRE && (child->is_input || child->is_output)) {
@ -970,6 +981,10 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
} }
} }
ast->children.swap(new_children); ast->children.swap(new_children);
if (ast->attributes.count("\\whitebox")) {
delete ast->attributes.at("\\whitebox");
ast->attributes.erase("\\whitebox");
}
ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false); ast->attributes["\\blackbox"] = AstNode::mkconst_int(1, false);
} }
@ -1010,6 +1025,7 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
current_module->nomem2reg = flag_nomem2reg; current_module->nomem2reg = flag_nomem2reg;
current_module->mem2reg = flag_mem2reg; current_module->mem2reg = flag_mem2reg;
current_module->lib = flag_lib; current_module->lib = flag_lib;
current_module->wb = flag_wb;
current_module->noopt = flag_noopt; current_module->noopt = flag_noopt;
current_module->icells = flag_icells; current_module->icells = flag_icells;
current_module->autowire = flag_autowire; current_module->autowire = flag_autowire;
@ -1026,7 +1042,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' // 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, 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 lib, bool wb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire)
{ {
current_ast = ast; current_ast = ast;
flag_dump_ast1 = dump_ast1; flag_dump_ast1 = dump_ast1;
@ -1040,6 +1056,7 @@ void AST::process(RTLIL::Design *design, AstNode *ast, bool dump_ast1, bool dump
flag_nomem2reg = nomem2reg; flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg; flag_mem2reg = mem2reg;
flag_lib = lib; flag_lib = lib;
flag_wb = wb;
flag_noopt = noopt; flag_noopt = noopt;
flag_icells = icells; flag_icells = icells;
flag_autowire = autowire; flag_autowire = autowire;
@ -1374,6 +1391,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
flag_nomem2reg = nomem2reg; flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg; flag_mem2reg = mem2reg;
flag_lib = lib; flag_lib = lib;
flag_wb = wb;
flag_noopt = noopt; flag_noopt = noopt;
flag_icells = icells; flag_icells = icells;
flag_autowire = autowire; flag_autowire = autowire;

View file

@ -283,13 +283,13 @@ namespace AST
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code // 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, 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 lib, bool wb, bool noopt, bool icells, bool nooverwrite, bool overwrite, bool defer, bool autowire);
// parametric modules are supported directly by the AST library // parametric modules are supported directly by the AST library
// therefore we need our own derivate of RTLIL::Module with overloaded virtual functions // therefore we need our own derivate of RTLIL::Module with overloaded virtual functions
struct AstModule : RTLIL::Module { struct AstModule : RTLIL::Module {
AstNode *ast; AstNode *ast;
bool nolatches, nomeminit, nomem2reg, mem2reg, lib, noopt, icells, autowire; bool nolatches, nomeminit, nomem2reg, mem2reg, lib, wb, noopt, icells, autowire;
~AstModule() YS_OVERRIDE; ~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, 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; 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;

View file

@ -148,6 +148,10 @@ struct VerilogFrontend : public Frontend {
log(" -lib\n"); log(" -lib\n");
log(" only create empty blackbox modules. This implies -DBLACKBOX.\n"); log(" only create empty blackbox modules. This implies -DBLACKBOX.\n");
log("\n"); log("\n");
log(" -wb\n");
log(" like -lib, except do not touch modules with the whitebox\n");
log(" attribute set. This also implies -DBLACKBOX.\n");
log("\n");
log(" -noopt\n"); log(" -noopt\n");
log(" don't perform basic optimizations (such as const folding) in the\n"); log(" don't perform basic optimizations (such as const folding) in the\n");
log(" high-level front-end.\n"); log(" high-level front-end.\n");
@ -228,6 +232,7 @@ struct VerilogFrontend : public Frontend {
norestrict_mode = false; norestrict_mode = false;
assume_asserts_mode = false; assume_asserts_mode = false;
lib_mode = false; lib_mode = false;
wb_mode = false;
default_nettype_wire = true; default_nettype_wire = true;
log_header(design, "Executing Verilog-2005 frontend.\n"); log_header(design, "Executing Verilog-2005 frontend.\n");
@ -329,11 +334,16 @@ struct VerilogFrontend : public Frontend {
flag_nodpi = true; flag_nodpi = true;
continue; continue;
} }
if (arg == "-lib") { if (arg == "-lib" && !wb_mode) {
lib_mode = true; lib_mode = true;
defines_map["BLACKBOX"] = string(); defines_map["BLACKBOX"] = string();
continue; continue;
} }
if (arg == "-wb" && !lib_mode) {
wb_mode = true;
defines_map["BLACKBOX"] = string();
continue;
}
if (arg == "-noopt") { if (arg == "-noopt") {
flag_noopt = true; flag_noopt = true;
continue; continue;
@ -429,7 +439,7 @@ struct VerilogFrontend : public Frontend {
if (flag_nodpi) if (flag_nodpi)
error_on_dpi_function(current_ast); 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, lib_mode, wb_mode, flag_noopt, flag_icells, flag_nooverwrite, flag_overwrite, flag_defer, default_nettype_wire);
if (!flag_nopp) if (!flag_nopp)
delete lexin; delete lexin;

View file

@ -72,6 +72,9 @@ namespace VERILOG_FRONTEND
// running in -lib mode // running in -lib mode
extern bool lib_mode; extern bool lib_mode;
// running in -wb mode
extern bool wb_mode;
// lexer input stream // lexer input stream
extern std::istream *lexin; extern std::istream *lexin;
} }

View file

@ -59,7 +59,7 @@ namespace VERILOG_FRONTEND {
std::vector<char> case_type_stack; std::vector<char> case_type_stack;
bool do_not_require_port_stubs; bool do_not_require_port_stubs;
bool default_nettype_wire; bool default_nettype_wire;
bool sv_mode, formal_mode, lib_mode; bool sv_mode, formal_mode, lib_mode, wb_mode;
bool noassert_mode, noassume_mode, norestrict_mode; bool noassert_mode, noassume_mode, norestrict_mode;
bool assume_asserts_mode, assert_assumes_mode; bool assume_asserts_mode, assert_assumes_mode;
bool current_wire_rand, current_wire_const; bool current_wire_rand, current_wire_const;
@ -1906,7 +1906,7 @@ basic_expr:
if ($4->substr(0, 1) != "'") if ($4->substr(0, 1) != "'")
frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str()); frontend_verilog_yyerror("Cast operation must be applied on sized constants e.g. (<expr>)<constval> , while %s is not a sized constant.", $4->c_str());
AstNode *bits = $2; AstNode *bits = $2;
AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); AstNode *val = const2ast(*$4, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode && !wb_mode);
if (val == NULL) if (val == NULL)
log_error("Value conversion failed: `%s'\n", $4->c_str()); log_error("Value conversion failed: `%s'\n", $4->c_str());
$$ = new AstNode(AST_TO_BITS, bits, val); $$ = new AstNode(AST_TO_BITS, bits, val);
@ -1917,7 +1917,7 @@ basic_expr:
frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str()); frontend_verilog_yyerror("Cast operation must be applied on sized constants, e.g. <ID>\'d0, while %s is not a sized constant.", $2->c_str());
AstNode *bits = new AstNode(AST_IDENTIFIER); AstNode *bits = new AstNode(AST_IDENTIFIER);
bits->str = *$1; bits->str = *$1;
AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); AstNode *val = const2ast(*$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode && !wb_mode);
if (val == NULL) if (val == NULL)
log_error("Value conversion failed: `%s'\n", $2->c_str()); log_error("Value conversion failed: `%s'\n", $2->c_str());
$$ = new AstNode(AST_TO_BITS, bits, val); $$ = new AstNode(AST_TO_BITS, bits, val);
@ -1925,14 +1925,14 @@ basic_expr:
delete $2; delete $2;
} | } |
TOK_CONSTVAL TOK_CONSTVAL { TOK_CONSTVAL TOK_CONSTVAL {
$$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); $$ = const2ast(*$1 + *$2, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode && !wb_mode);
if ($$ == NULL || (*$2)[0] != '\'') if ($$ == NULL || (*$2)[0] != '\'')
log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str()); log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str());
delete $1; delete $1;
delete $2; delete $2;
} | } |
TOK_CONSTVAL { TOK_CONSTVAL {
$$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode); $$ = const2ast(*$1, case_type_stack.size() == 0 ? 0 : case_type_stack.back(), !lib_mode && !wb_mode);
if ($$ == NULL) if ($$ == NULL)
log_error("Value conversion failed: `%s'\n", $1->c_str()); log_error("Value conversion failed: `%s'\n", $1->c_str());
delete $1; delete $1;

View file

@ -207,9 +207,12 @@ bool RTLIL::Const::is_fully_undef() const
return true; 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 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; std::vector<RTLIL::Module*> result;
result.reserve(modules_.size()); result.reserve(modules_.size());
for (auto &it : modules_) 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); result.push_back(it.second);
return result; return result;
} }
@ -599,7 +602,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules() const
std::vector<RTLIL::Module*> result; std::vector<RTLIL::Module*> result;
result.reserve(modules_.size()); result.reserve(modules_.size());
for (auto &it : modules_) 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); result.push_back(it.second);
return result; return result;
} }
@ -609,7 +612,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules_warn() const
std::vector<RTLIL::Module*> result; std::vector<RTLIL::Module*> result;
result.reserve(modules_.size()); result.reserve(modules_.size());
for (auto &it : modules_) for (auto &it : modules_)
if (it.second->get_bool_attribute("\\blackbox")) if (it.second->get_blackbox_attribute())
continue; continue;
else if (selected_whole_module(it.first)) else if (selected_whole_module(it.first))
result.push_back(it.second); result.push_back(it.second);

View file

@ -566,9 +566,13 @@ struct RTLIL::AttrObject
{ {
dict<RTLIL::IdString, RTLIL::Const> attributes; 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_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 set_strpool_attribute(RTLIL::IdString id, const pool<string> &data);
void add_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; pool<string> get_strpool_attribute(RTLIL::IdString id) const;

View file

@ -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); RTLIL::Module *mod = design->modules_.at(it.second->type);
if (!design->selected_whole_module(mod->name)) if (!design->selected_whole_module(mod->name))
continue; continue;
if (mod->get_bool_attribute("\\blackbox")) if (mod->get_blackbox_attribute())
continue; continue;
if (it.second->hasPort(name)) if (it.second->hasPort(name))
continue; continue;

View file

@ -128,7 +128,7 @@ struct BugpointPass : public Pass {
{ {
for (auto &it : design_copy->modules_) for (auto &it : design_copy->modules_)
{ {
if (it.second->get_bool_attribute("\\blackbox")) if (it.second->get_blackbox_attribute())
continue; continue;
if (index++ == seed) if (index++ == seed)
@ -143,7 +143,7 @@ struct BugpointPass : public Pass {
{ {
for (auto mod : design_copy->modules()) for (auto mod : design_copy->modules())
{ {
if (mod->get_bool_attribute("\\blackbox")) if (mod->get_blackbox_attribute())
continue; continue;
for (auto wire : mod->wires()) for (auto wire : mod->wires())
@ -168,7 +168,7 @@ struct BugpointPass : public Pass {
{ {
for (auto mod : design_copy->modules()) for (auto mod : design_copy->modules())
{ {
if (mod->get_bool_attribute("\\blackbox")) if (mod->get_blackbox_attribute())
continue; continue;
for (auto &it : mod->cells_) for (auto &it : mod->cells_)
@ -186,7 +186,7 @@ struct BugpointPass : public Pass {
{ {
for (auto mod : design_copy->modules()) for (auto mod : design_copy->modules())
{ {
if (mod->get_bool_attribute("\\blackbox")) if (mod->get_blackbox_attribute())
continue; continue;
for (auto cell : mod->cells()) for (auto cell : mod->cells())

View file

@ -128,6 +128,45 @@ struct SetattrPass : public Pass {
} }
} SetattrPass; } 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 { struct SetparamPass : public Pass {
SetparamPass() : Pass("setparam", "set/unset parameters on objects") { } SetparamPass() : Pass("setparam", "set/unset parameters on objects") { }
void help() YS_OVERRIDE void help() YS_OVERRIDE

View file

@ -574,7 +574,7 @@ struct ShowWorker
if (!design->selected_module(module->name)) if (!design->selected_module(module->name))
continue; continue;
if (design->selected_whole_module(module->name)) { 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)); // log("Skipping blackbox module %s.\n", id2cstr(module->name));
continue; continue;
} else } else
@ -790,7 +790,7 @@ struct ShowPass : public Pass {
if (format != "ps" && format != "dot") { if (format != "ps" && format != "dot") {
int modcount = 0; int modcount = 0;
for (auto &mod_it : design->modules_) { for (auto &mod_it : design->modules_) {
if (mod_it.second->get_bool_attribute("\\blackbox")) if (mod_it.second->get_blackbox_attribute())
continue; continue;
if (mod_it.second->cells_.empty() && mod_it.second->connections().empty()) if (mod_it.second->cells_.empty() && mod_it.second->connections().empty())
continue; continue;

View file

@ -134,7 +134,7 @@ struct EquivOptPass:public ScriptPass
opts = " -map <filename> ..."; opts = " -map <filename> ...";
else else
opts = techmap_opts; opts = techmap_opts;
run("techmap -D EQUIV -autoproc" + opts); run("techmap -wb -D EQUIV -autoproc" + opts);
} }
if (check_label("prove")) { if (check_label("prove")) {

View file

@ -346,9 +346,9 @@ bool expand_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_check
} }
RTLIL::Module *mod = design->modules_[cell->type]; 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) 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()); cell->type.c_str(), module->name.c_str(), cell->name.c_str());
continue; continue;
} }
@ -451,7 +451,7 @@ void hierarchy_worker(RTLIL::Design *design, std::set<RTLIL::Module*, IdString::
if (indent == 0) if (indent == 0)
log("Top module: %s\n", mod->name.c_str()); 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()); log("Used module: %*s%s\n", indent, "", mod->name.c_str());
used.insert(mod); used.insert(mod);
@ -491,7 +491,7 @@ void hierarchy_clean(RTLIL::Design *design, RTLIL::Module *top, bool purge_lib)
int del_counter = 0; int del_counter = 0;
for (auto mod : del_modules) { for (auto mod : del_modules) {
if (!purge_lib && mod->get_bool_attribute("\\blackbox")) if (!purge_lib && mod->get_blackbox_attribute())
continue; continue;
log("Removing unused module `%s'.\n", mod->name.c_str()); log("Removing unused module `%s'.\n", mod->name.c_str());
design->modules_.erase(mod->name); design->modules_.erase(mod->name);
@ -910,7 +910,7 @@ struct HierarchyPass : public Pass {
if (m == nullptr) if (m == nullptr)
continue; 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); IdString new_m_name = m->derive(design, cell->parameters, true);
if (new_m_name.empty()) if (new_m_name.empty())
continue; continue;

View file

@ -75,7 +75,7 @@ struct UniquifyPass : public Pass {
if (tmod == nullptr) if (tmod == nullptr)
continue; continue;
if (tmod->get_bool_attribute("\\blackbox")) if (tmod->get_blackbox_attribute())
continue; continue;
if (tmod->get_bool_attribute("\\unique") && newname == tmod->name) if (tmod->get_bool_attribute("\\unique") && newname == tmod->name)

View file

@ -254,7 +254,7 @@ void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL:
if (flag_flatten) { if (flag_flatten) {
log_push(); 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(); log_pop();
} }
} }
@ -308,7 +308,7 @@ void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL
if (flag_flatten) { if (flag_flatten) {
log_push(); log_push();
Pass::call_on_module(design, module, "flatten;;"); Pass::call_on_module(design, module, "flatten -wb;;");
log_pop(); 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(" also create an 'assert' cell that checks if trigger is always low.\n");
log("\n"); log("\n");
log(" -flatten\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("\n"); log("\n");
log(" miter -assert [options] module [miter_name]\n"); log(" miter -assert [options] module [miter_name]\n");
@ -399,7 +399,7 @@ struct MiterPass : public Pass {
log(" keep module output ports.\n"); log(" keep module output ports.\n");
log("\n"); log("\n");
log(" -flatten\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");
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE

View file

@ -664,7 +664,7 @@ struct DfflibmapPass : public Pass {
logmap_all(); logmap_all();
for (auto &it : design->modules_) 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); dfflibmap(design, it.second, prepare_mode);
cell_mappings.clear(); cell_mappings.clear();

View file

@ -599,7 +599,7 @@ struct SimplemapPass : public Pass {
simplemap_get_mappers(mappers); simplemap_get_mappers(mappers);
for (auto mod : design->modules()) { for (auto mod : design->modules()) {
if (!design->selected(mod)) if (!design->selected(mod) || mod->get_blackbox_attribute())
continue; continue;
std::vector<RTLIL::Cell*> cells = mod->cells(); std::vector<RTLIL::Cell*> cells = mod->cells();
for (auto cell : cells) { for (auto cell : cells) {

View file

@ -84,6 +84,7 @@ struct TechmapWorker
bool flatten_mode; bool flatten_mode;
bool recursive_mode; bool recursive_mode;
bool autoproc_mode; bool autoproc_mode;
bool ignore_wb;
TechmapWorker() TechmapWorker()
{ {
@ -92,6 +93,7 @@ struct TechmapWorker
flatten_mode = false; flatten_mode = false;
recursive_mode = false; recursive_mode = false;
autoproc_mode = false; autoproc_mode = false;
ignore_wb = false;
} }
std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose) 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"; 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; return false;
bool log_continue = false; bool log_continue = false;
@ -472,7 +474,7 @@ struct TechmapWorker
RTLIL::Module *tpl = map->modules_[tpl_name]; RTLIL::Module *tpl = map->modules_[tpl_name];
std::map<RTLIL::IdString, RTLIL::Const> parameters(cell->parameters.begin(), cell->parameters.end()); 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; continue;
if (!flatten_mode) if (!flatten_mode)
@ -925,6 +927,9 @@ struct TechmapPass : public Pass {
log(" -autoproc\n"); log(" -autoproc\n");
log(" Automatically call \"proc\" on implementations that contain processes.\n"); log(" Automatically call \"proc\" on implementations that contain processes.\n");
log("\n"); log("\n");
log(" -wb\n");
log(" Ignore the 'whitebox' attribute on cell implementations.\n");
log("\n");
log(" -assert\n"); log(" -assert\n");
log(" this option will cause techmap to exit with an error if it can't map\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"); log(" a selected cell. only cell types that end on an underscore are accepted\n");
@ -1068,6 +1073,10 @@ struct TechmapPass : public Pass {
worker.autoproc_mode = true; worker.autoproc_mode = true;
continue; continue;
} }
if (args[argidx] == "-wb") {
worker.ignore_wb = true;
continue;
}
break; break;
} }
extra_args(args, argidx, design); extra_args(args, argidx, design);
@ -1145,7 +1154,7 @@ struct FlattenPass : public Pass {
{ {
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n"); log("\n");
log(" flatten [selection]\n"); log(" flatten [options] [selection]\n");
log("\n"); log("\n");
log("This pass flattens the design by replacing cells by their implementation. This\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"); 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("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n");
log("flattened by this command.\n"); log("flattened by this command.\n");
log("\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 void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{ {
log_header(design, "Executing FLATTEN pass (flatten design).\n"); log_header(design, "Executing FLATTEN pass (flatten design).\n");
log_push(); log_push();
extra_args(args, 1, design);
TechmapWorker worker; TechmapWorker worker;
worker.flatten_mode = true; 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; std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
for (auto module : design->modules()) for (auto module : design->modules())
celltypeMap[module->name].insert(module->name); celltypeMap[module->name].insert(module->name);
@ -1209,7 +1230,7 @@ struct FlattenPass : public Pass {
dict<RTLIL::IdString, RTLIL::Module*> new_modules; dict<RTLIL::IdString, RTLIL::Module*> new_modules;
for (auto mod : vector<Module*>(design->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; new_modules[mod->name] = mod;
} else { } else {
log("Deleting now unused module %s.\n", log_id(mod)); log("Deleting now unused module %s.\n", log_id(mod));