3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-08 10:25:19 +00:00

Merge branch 'master' into map_cells_before_map_luts

This commit is contained in:
Eddie Hung 2019-04-21 14:24:50 -07:00
commit a3371e118b
47 changed files with 443 additions and 189 deletions

View file

@ -111,7 +111,7 @@ OBJS = kernel/version_$(GIT_REV).o
# is just a symlink to your actual ABC working directory, as 'make mrproper'
# will remove the 'abc' directory and you do not want to accidentally
# delete your work on ABC..
ABCREV = 2ddc57d
ABCREV = 3709744
ABCPULL = 1
ABCURL ?= https://github.com/berkeley-abc/abc
ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1

View file

@ -312,10 +312,14 @@ Verilog Attributes and non-standard features
passes to identify input and output ports of cells. The Verilog backend
also does not output blackbox modules on default.
- The ``dynports'' attribute is used by the Verilog front-end to mark modules
- 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
that have ports with a width that depends on a parameter.
- The ``hdlname'' attribute is used by some passes to document the original
- The ``hdlname`` attribute is used by some passes to document the original
(HDL) name of a module when renaming a module.
- The ``keep`` attribute on cells and wires is used to mark objects that should

View file

@ -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)

View file

@ -340,7 +340,7 @@ struct BtorWorker
if (cell->type == "$lt") btor_op = "lt";
if (cell->type == "$le") btor_op = "lte";
if (cell->type.in("$eq", "$eqx")) btor_op = "eq";
if (cell->type.in("$ne", "$nex")) btor_op = "ne";
if (cell->type.in("$ne", "$nex")) btor_op = "neq";
if (cell->type == "$ge") btor_op = "gte";
if (cell->type == "$gt") btor_op = "gt";
log_assert(!btor_op.empty());

View file

@ -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);

View file

@ -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;

View file

@ -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));

View file

@ -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())

View file

@ -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)

View file

@ -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);

View file

@ -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))

View file

@ -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_lib, flag_wb, 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;
@ -956,7 +956,18 @@ static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast
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) {
blackbox_module:
std::vector<AstNode*> new_children;
for (auto child : ast->children) {
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);
if (ast->attributes.count("\\whitebox")) {
delete ast->attributes.at("\\whitebox");
ast->attributes.erase("\\whitebox");
}
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->mem2reg = flag_mem2reg;
current_module->lib = flag_lib;
current_module->wb = flag_wb;
current_module->noopt = flag_noopt;
current_module->icells = flag_icells;
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'
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;
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_mem2reg = mem2reg;
flag_lib = lib;
flag_wb = wb;
flag_noopt = noopt;
flag_icells = icells;
flag_autowire = autowire;
@ -1374,6 +1391,7 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
flag_nomem2reg = nomem2reg;
flag_mem2reg = mem2reg;
flag_lib = lib;
flag_wb = wb;
flag_noopt = noopt;
flag_icells = icells;
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
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
// 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, lib, wb, 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;

View file

@ -47,16 +47,20 @@ struct IlangFrontend : public Frontend {
log(" -nooverwrite\n");
log(" ignore re-definitions of modules. (the default behavior is to\n");
log(" create an error message if the existing module is not a blackbox\n");
log(" module, and overwrite the existing module if it is a blackbox module.)\n");
log(" module, and overwrite the existing module if it is a blackbox module.)\n");
log("\n");
log(" -overwrite\n");
log(" overwrite existing modules with the same name\n");
log("\n");
log(" -lib\n");
log(" only create empty blackbox modules\n");
log("\n");
}
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
{
ILANG_FRONTEND::flag_nooverwrite = false;
ILANG_FRONTEND::flag_overwrite = false;
ILANG_FRONTEND::flag_lib = false;
log_header(design, "Executing ILANG frontend.\n");
@ -73,6 +77,10 @@ struct IlangFrontend : public Frontend {
ILANG_FRONTEND::flag_overwrite = true;
continue;
}
if (arg == "-lib") {
ILANG_FRONTEND::flag_lib = true;
continue;
}
break;
}
extra_args(f, filename, args, argidx);

View file

@ -34,6 +34,7 @@ namespace ILANG_FRONTEND {
extern RTLIL::Design *current_design;
extern bool flag_nooverwrite;
extern bool flag_overwrite;
extern bool flag_lib;
}
YOSYS_NAMESPACE_END

View file

@ -37,7 +37,7 @@ namespace ILANG_FRONTEND {
std::vector<std::vector<RTLIL::SwitchRule*>*> switch_stack;
std::vector<RTLIL::CaseRule*> case_stack;
dict<RTLIL::IdString, RTLIL::Const> attrbuf;
bool flag_nooverwrite, flag_overwrite;
bool flag_nooverwrite, flag_overwrite, flag_lib;
bool delete_current_module;
}
using namespace ILANG_FRONTEND;
@ -98,7 +98,7 @@ module:
delete_current_module = false;
if (current_design->has($2)) {
RTLIL::Module *existing_mod = current_design->module($2);
if (!flag_overwrite && attrbuf.count("\\blackbox") && attrbuf.at("\\blackbox").as_bool()) {
if (!flag_overwrite && (flag_lib || (attrbuf.count("\\blackbox") && attrbuf.at("\\blackbox").as_bool()))) {
log("Ignoring blackbox re-definition of module %s.\n", $2);
delete_current_module = true;
} else if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
@ -124,6 +124,8 @@ module:
current_module->fixup_ports();
if (delete_current_module)
delete current_module;
else if (flag_lib)
current_module->makeblackbox();
current_module = nullptr;
} EOL;

View file

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

View file

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

View file

@ -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, lib_mode, wb_mode;
bool noassert_mode, noassume_mode, norestrict_mode;
bool assume_asserts_mode, assert_assumes_mode;
bool current_wire_rand, current_wire_const;
@ -1906,7 +1906,7 @@ basic_expr:
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());
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)
log_error("Value conversion failed: `%s'\n", $4->c_str());
$$ = 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());
AstNode *bits = new AstNode(AST_IDENTIFIER);
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)
log_error("Value conversion failed: `%s'\n", $2->c_str());
$$ = new AstNode(AST_TO_BITS, bits, val);
@ -1925,14 +1925,14 @@ basic_expr:
delete $2;
} |
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] != '\'')
log_error("Value conversion failed: `%s%s'\n", $1->c_str(), $2->c_str());
delete $1;
delete $2;
} |
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)
log_error("Value conversion failed: `%s'\n", $1->c_str());
delete $1;

View file

@ -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);
@ -641,6 +644,30 @@ RTLIL::Module::~Module()
delete it->second;
}
void RTLIL::Module::makeblackbox()
{
pool<RTLIL::Wire*> delwires;
for (auto it = wires_.begin(); it != wires_.end(); ++it)
if (!it->second->port_input && !it->second->port_output)
delwires.insert(it->second);
for (auto it = memories.begin(); it != memories.end(); ++it)
delete it->second;
memories.clear();
for (auto it = cells_.begin(); it != cells_.end(); ++it)
delete it->second;
cells_.clear();
for (auto it = processes.begin(); it != processes.end(); ++it)
delete it->second;
processes.clear();
remove(delwires);
set_bool_attribute("\\blackbox");
}
void RTLIL::Module::reprocess_module(RTLIL::Design *, dict<RTLIL::IdString, RTLIL::Module *>)
{
log_error("Cannot reprocess_module module `%s' !\n", id2cstr(name));

View file

@ -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;
@ -976,6 +980,7 @@ public:
virtual void sort();
virtual void check();
virtual void optimize();
virtual void makeblackbox();
void connect(const RTLIL::SigSig &conn);
void connect(const RTLIL::SigSpec &lhs, const RTLIL::SigSpec &rhs);

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);
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;

View file

@ -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())

View file

@ -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

View file

@ -237,15 +237,34 @@ struct ShowWorker
int idx = single_idx_count++;
for (int rep, i = int(sig.chunks().size())-1; i >= 0; i -= rep) {
const RTLIL::SigChunk &c = sig.chunks().at(i);
net = gen_signode_simple(c, false);
log_assert(!net.empty());
if (!driver && c.wire == nullptr) {
RTLIL::State s1 = c.data.front();
for (auto s2 : c.data)
if (s1 != s2)
goto not_const_stream;
net.clear();
} else {
not_const_stream:
net = gen_signode_simple(c, false);
log_assert(!net.empty());
}
for (rep = 1; i-rep >= 0 && c == sig.chunks().at(i-rep); rep++) {}
std::string repinfo = rep > 1 ? stringf("%dx ", rep) : "";
if (driver) {
log_assert(!net.empty());
label_string += stringf("<s%d> %d:%d - %s%d:%d |", i, pos, pos-c.width+1, repinfo.c_str(), c.offset+c.width-1, c.offset);
net_conn_map[net].in.insert(stringf("x%d:s%d", idx, i));
net_conn_map[net].bits = rep*c.width;
net_conn_map[net].color = nextColor(c, net_conn_map[net].color);
} else
if (net.empty()) {
log_assert(rep == 1);
label_string += stringf("%c -&gt; %d:%d |",
c.data.front() == State::S0 ? '0' :
c.data.front() == State::S1 ? '1' :
c.data.front() == State::Sx ? 'X' :
c.data.front() == State::Sz ? 'Z' : '?',
pos, pos-rep*c.width+1);
} else {
label_string += stringf("<s%d> %s%d:%d - %d:%d |", i, repinfo.c_str(), c.offset+c.width-1, c.offset, pos, pos-rep*c.width+1);
net_conn_map[net].out.insert(stringf("x%d:s%d", idx, i));
@ -555,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
@ -771,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;

View file

@ -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")) {

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];
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;

View file

@ -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)

View file

@ -744,7 +744,8 @@ grow_read_ports:;
if (clken) {
clock_domains[pi.clocks] = clkdom;
clock_polarities[pi.clkpol] = clkdom.second;
read_transp[pi.transp] = transp;
if (!pi.make_transp)
read_transp[pi.transp] = transp;
pi.sig_clock = clkdom.first;
pi.sig_en = rd_en[cell_port_i];
pi.effective_clkpol = clkdom.second;

View file

@ -83,8 +83,8 @@ They are declared like state variables, just using the `udata` statement:
udata <int> min_data_width max_data_width
udata <IdString> data_port_name
They are atomatically initialzed to the default constructed value of their type
when ther pattern matcher object is constructed.
They are automatically initialized to the default constructed value of their type
when the pattern matcher object is constructed.
Embedded C++ code
-----------------
@ -158,7 +158,7 @@ Finally, `filter <expression>` narrows down the remaining list of cells. For
performance reasons `filter` statements should only be used for things that
can't be done using `select` and `index`.
The `optional` statement marks optional matches. I.e. the matcher will also
The `optional` statement marks optional matches. That is, the matcher will also
explore the case where `mul` is set to `nullptr`. Without the `optional`
statement a match may only be assigned nullptr when one of the `if` expressions
evaluates to `false`.

View file

@ -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,10 +381,15 @@ 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;
bool shiftx = initial_val.is_fully_undef();
for (size_t i = 0; i < sw->cases.size(); i++) {
int case_idx = sw->cases.size() - i - 1;
RTLIL::CaseRule *cs2 = sw->cases[case_idx];
@ -349,33 +398,6 @@ RTLIL::SigSpec signal_to_mux_tree(RTLIL::Module *mod, SnippetSwCache &swcache, d
append_pmux(mod, sw->signal, cs2->compare, value, last_mux_cell, sw, ifxmode);
else
result = gen_mux(mod, sw->signal, cs2->compare, value, result, last_mux_cell, sw, ifxmode);
// Ignore output values which are entirely don't care
if (shiftx && !value.is_fully_undef()) {
// Keep checking if case condition is the same as the current case index
if (cs2->compare.size() == 1 && cs2->compare.front().is_fully_const())
shiftx = (cs2->compare.front().as_int() == case_idx);
else
shiftx = false;
}
}
// Transform into a $shiftx where possible
if (shiftx && last_mux_cell && last_mux_cell->type == "$pmux") {
// Create bit-blasted $shiftx-es that shifts by the address line used in the case statement
auto pmux_b_port = last_mux_cell->getPort("\\B");
auto pmux_y_port = last_mux_cell->getPort("\\Y");
int width = last_mux_cell->getParam("\\WIDTH").as_int();
for (int i = 0; i < width; ++i) {
RTLIL::SigSpec a_port;
// Because we went in reverse order above, un-reverse $pmux's B port here
for (int j = pmux_b_port.size()/width-1; j >= 0; --j)
a_port.append(pmux_b_port.extract(j*width+i, 1));
// Create a $shiftx that shifts by the address line used in the case statement
mod->addShiftx(NEW_ID, a_port, sw->signal, pmux_y_port.extract(i, 1));
}
// Disconnect $pmux by replacing its output port with a floating wire
last_mux_cell->setPort("\\Y", mod->addWire(NEW_ID, width));
}
}

View file

@ -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;
}
}

View file

@ -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

View file

@ -934,6 +934,32 @@ struct MutatePass : public Pass {
return;
}
if (opts.module.empty())
log_cmd_error("Missing -module argument.\n");
Module *module = design->module(opts.module);
if (module == nullptr)
log_cmd_error("Module %s not found.\n", log_id(opts.module));
if (opts.cell.empty())
log_cmd_error("Missing -cell argument.\n");
Cell *cell = module->cell(opts.cell);
if (cell == nullptr)
log_cmd_error("Cell %s not found in module %s.\n", log_id(opts.cell), log_id(opts.module));
if (opts.port.empty())
log_cmd_error("Missing -port argument.\n");
if (!cell->hasPort(opts.port))
log_cmd_error("Port %s not found on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell));
if (opts.portbit < 0)
log_cmd_error("Missing -portbit argument.\n");
if (GetSize(cell->getPort(opts.port)) <= opts.portbit)
log_cmd_error("Out-of-range -portbit argument for port %s on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell));
if (opts.mode == "inv") {
mutate_inv(design, opts);
return;
@ -944,6 +970,12 @@ struct MutatePass : public Pass {
return;
}
if (opts.ctrlbit < 0)
log_cmd_error("Missing -ctrlbit argument.\n");
if (GetSize(cell->getPort(opts.port)) <= opts.ctrlbit)
log_cmd_error("Out-of-range -ctrlbit argument for port %s on cell %s.%s.\n", log_id(opts.port), log_id(opts.module), log_id(opts.cell));
if (opts.mode == "cnot0" || opts.mode == "cnot1") {
mutate_cnot(design, opts, opts.mode == "cnot1");
return;

View file

@ -29,17 +29,17 @@
// Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025
// http://en.wikipedia.org/wiki/Topological_sorting
#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put"
#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; if; mfs2"
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; cover {I} {P}"
#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put"
#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}"
#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
#define ABC_FAST_COMMAND_LUT "strash; dretime; if"
#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}"
#define ABC_FAST_COMMAND_DFL "strash; dretime; map"
#define ABC_FAST_COMMAND_LIB "strash; dretime; retime {D}; map {D}"
#define ABC_FAST_COMMAND_CTR "strash; dretime; retime {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
#define ABC_FAST_COMMAND_LUT "strash; dretime; retime {D}; if"
#define ABC_FAST_COMMAND_SOP "strash; dretime; retime {D}; cover -I {I} -P {P}"
#define ABC_FAST_COMMAND_DFL "strash; dretime; retime {D}; map"
#include "kernel/register.h"
#include "kernel/sigtools.h"
@ -331,19 +331,23 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp
{
std::string abc_sname = abc_name.substr(1);
if (abc_sname.substr(0, 5) == "ys__n") {
int sid = std::stoi(abc_sname.substr(5));
bool inv = abc_sname.back() == 'v';
for (auto sig : signal_list) {
if (sig.id == sid && sig.bit.wire != nullptr) {
std::stringstream sstr;
sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1);
if (sig.bit.wire->width != 1)
sstr << "[" << sig.bit.offset << "]";
if (inv)
sstr << "_inv";
if (orig_wire != nullptr)
*orig_wire = sig.bit.wire;
return sstr.str();
if (inv) abc_sname.pop_back();
abc_sname.erase(0, 5);
if (abc_sname.find_last_not_of("012345689") == std::string::npos) {
int sid = std::stoi(abc_sname);
for (auto sig : signal_list) {
if (sig.id == sid && sig.bit.wire != nullptr) {
std::stringstream sstr;
sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1);
if (sig.bit.wire->width != 1)
sstr << "[" << sig.bit.offset << "]";
if (inv)
sstr << "_inv";
if (orig_wire != nullptr)
*orig_wire = sig.bit.wire;
return sstr.str();
}
}
}
}
@ -731,10 +735,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
else
abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL;
if (script_file.empty() && !delay_target.empty())
for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1))
abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8);
for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3);
@ -1726,7 +1726,7 @@ struct AbcPass : public Pass {
signal_init[initsig[i]] = State::S0;
break;
case State::S1:
signal_init[initsig[i]] = State::S0;
signal_init[initsig[i]] = State::S1;
break;
default:
break;

View file

@ -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();

View file

@ -71,9 +71,9 @@ struct PmuxtreePass : public Pass {
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" pmuxtree [options] [selection]\n");
log(" pmuxtree [selection]\n");
log("\n");
log("This pass transforms $pmux cells to a trees of $mux cells.\n");
log("This pass transforms $pmux cells to trees of $mux cells.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE

View file

@ -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) {

View file

@ -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");
@ -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));

View file

@ -85,7 +85,7 @@ module cyclonev_lcell_comb
begin
upper_lut_value = lut4(mask[31:16], dataa, datab, datac, datad);
lower_lut_value = lut4(mask[15:0], dataa, datab, datac, datad);
lut5 = (datae) ? upper_mask_value : lower_mask_value;
lut5 = (datae) ? upper_lut_value : lower_lut_value;
end
endfunction // lut5
@ -95,15 +95,16 @@ module cyclonev_lcell_comb
input dataa, datab, datac, datad, datae, dataf;
reg upper_lut_value;
reg lower_lut_value;
reg out_0, out_1, out_2, out_3;
begin
upper_lut_value = lut5(mask[63:32], dataa, datab, datac, datad, datae);
lower_lut_value = lut5(mask[31:0], dataa, datab, datac, datad, datae);
lut6 = (dataf) ? upper_mask_value : lower_mask_value;
lut6 = (dataf) ? upper_lut_value : lower_lut_value;
end
endfunction // lut6
assign {mask_a, mask_b, mask_c, mask_d} = {lut_mask[15:0], lut_mask[31:16], lut_mask[47:32], lut_mask[63:48]};
`ifdef ADVANCED_ALM
always @(*) begin
if(extended_lut == "on")
shared_lut_alm = datag;
@ -115,6 +116,11 @@ module cyclonev_lcell_comb
out_2 = lut4(mask_c, dataa, datab, datac, datad);
out_3 = lut4(mask_d, dataa, datab, shared_lut_alm, datad);
end
`else
`ifdef DEBUG
initial $display("Advanced ALM lut combine is not implemented yet");
`endif
`endif
endmodule // cyclonev_lcell_comb

View file

@ -30,10 +30,15 @@ module GND(output G);
endmodule
module IBUF(output O, input I);
parameter IOSTANDARD = "default";
parameter IBUF_LOW_PWR = 0;
assign O = I;
endmodule
module OBUF(output O, input I);
parameter IOSTANDARD = "default";
parameter DRIVE = 12;
parameter SLEW = "SLOW";
assign O = I;
endmodule
@ -41,6 +46,42 @@ module BUFG(output O, input I);
assign O = I;
endmodule
module BUFGCTRL(
output O,
input I0, input I1,
input S0, input S1,
input CE0, input CE1,
input IGNORE0, input IGNORE1);
parameter [0:0] INIT_OUT = 1'b0;
parameter PRESELECT_I0 = "FALSE";
parameter PRESELECT_I1 = "FALSE";
parameter [0:0] IS_CE0_INVERTED = 1'b0;
parameter [0:0] IS_CE1_INVERTED = 1'b0;
parameter [0:0] IS_S0_INVERTED = 1'b0;
parameter [0:0] IS_S1_INVERTED = 1'b0;
parameter [0:0] IS_IGNORE0_INVERTED = 1'b0;
parameter [0:0] IS_IGNORE1_INVERTED = 1'b0;
wire I0_internal = ((CE0 ^ IS_CE0_INVERTED) ? I0 : INIT_OUT);
wire I1_internal = ((CE1 ^ IS_CE1_INVERTED) ? I1 : INIT_OUT);
wire S0_true = (S0 ^ IS_S0_INVERTED);
wire S1_true = (S1 ^ IS_S1_INVERTED);
assign O = S0_true ? I0_internal : (S1_true ? I1_internal : INIT_OUT);
endmodule
module BUFHCE(output O, input I, input CE);
parameter [0:0] INIT_OUT = 1'b0;
parameter CE_TYPE = "SYNC";
parameter [0:0] IS_CE_INVERTED = 1'b0;
assign O = ((CE ^ IS_CE_INVERTED) ? I : INIT_OUT);
endmodule
// module OBUFT(output O, input I, T);
// assign O = T ? 1'bz : I;
// endmodule
@ -98,6 +139,22 @@ module LUT6(output O, input I0, I1, I2, I3, I4, I5);
assign O = I0 ? s1[1] : s1[0];
endmodule
module LUT6_2(output O6, output O5, input I0, I1, I2, I3, I4, I5);
parameter [63:0] INIT = 0;
wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
assign O6 = I0 ? s1[1] : s1[0];
wire [15: 0] s5_4 = I4 ? INIT[31:16] : INIT[15: 0];
wire [ 7: 0] s5_3 = I3 ? s5_4[15: 8] : s5_4[ 7: 0];
wire [ 3: 0] s5_2 = I2 ? s5_3[ 7: 4] : s5_3[ 3: 0];
wire [ 1: 0] s5_1 = I1 ? s5_2[ 3: 2] : s5_2[ 1: 0];
assign O5 = I0 ? s5_1[1] : s5_1[0];
endmodule
module MUXCY(output O, input CI, DI, S);
assign O = S ? CI : DI;
endmodule

View file

@ -28,12 +28,12 @@ function xtract_cell_decl()
# xtract_cell_decl BUFG
xtract_cell_decl BUFGCE
xtract_cell_decl BUFGCE_1
xtract_cell_decl BUFGCTRL
#xtract_cell_decl BUFGCTRL
xtract_cell_decl BUFGMUX
xtract_cell_decl BUFGMUX_1
xtract_cell_decl BUFGMUX_CTRL
xtract_cell_decl BUFH
xtract_cell_decl BUFHCE
#xtract_cell_decl BUFHCE
xtract_cell_decl BUFIO
xtract_cell_decl BUFMR
xtract_cell_decl BUFMRCE
@ -92,7 +92,7 @@ function xtract_cell_decl()
# xtract_cell_decl LUT4
# xtract_cell_decl LUT5
# xtract_cell_decl LUT6
xtract_cell_decl LUT6_2
#xtract_cell_decl LUT6_2
xtract_cell_decl MMCME2_ADV
xtract_cell_decl MMCME2_BASE
# xtract_cell_decl MUXF7

View file

@ -30,29 +30,6 @@ module BUFGCE_1 (...);
input CE, I;
endmodule
module BUFGCTRL (...);
output O;
input CE0;
input CE1;
input I0;
input I1;
input IGNORE0;
input IGNORE1;
input S0;
input S1;
parameter integer INIT_OUT = 0;
parameter PRESELECT_I0 = "FALSE";
parameter PRESELECT_I1 = "FALSE";
parameter [0:0] IS_CE0_INVERTED = 1'b0;
parameter [0:0] IS_CE1_INVERTED = 1'b0;
parameter [0:0] IS_I0_INVERTED = 1'b0;
parameter [0:0] IS_I1_INVERTED = 1'b0;
parameter [0:0] IS_IGNORE0_INVERTED = 1'b0;
parameter [0:0] IS_IGNORE1_INVERTED = 1'b0;
parameter [0:0] IS_S0_INVERTED = 1'b0;
parameter [0:0] IS_S1_INVERTED = 1'b0;
endmodule
module BUFGMUX (...);
parameter CLK_SEL_TYPE = "SYNC";
output O;
@ -77,15 +54,6 @@ module BUFH (...);
input I;
endmodule
module BUFHCE (...);
parameter CE_TYPE = "SYNC";
parameter integer INIT_OUT = 0;
parameter [0:0] IS_CE_INVERTED = 1'b0;
output O;
input CE;
input I;
endmodule
module BUFIO (...);
output O;
input I;
@ -2420,12 +2388,6 @@ module LDPE (...);
input D, G, GE, PRE;
endmodule
module LUT6_2 (...);
parameter [63:0] INIT = 64'h0000000000000000;
input I0, I1, I2, I3, I4, I5;
output O5, O6;
endmodule
module MMCME2_ADV (...);
parameter BANDWIDTH = "OPTIMIZED";
parameter real CLKFBOUT_MULT_F = 5.000;

View file

@ -28,14 +28,14 @@ module \$_DFF_P_ (input D, C, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPL
module \$_DFFE_NP_ (input D, C, E, output Q); FDRE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
module \$_DFFE_PP_ (input D, C, E, output Q); FDRE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(E), .R(1'b0)); endmodule
module \$_DFF_NN0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule
module \$_DFF_NN0_ (input D, C, R, output Q); \$_DFF_NP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
module \$_DFF_NP0_ (input D, C, R, output Q); FDCE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule
module \$_DFF_PN0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR(!R)); endmodule
module \$_DFF_PN0_ (input D, C, R, output Q); \$_DFF_PP0_ _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
module \$_DFF_PP0_ (input D, C, R, output Q); FDCE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .CLR( R)); endmodule
module \$_DFF_NN1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule
module \$_DFF_NN1_ (input D, C, R, output Q); \$_DFF_NP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
module \$_DFF_NP1_ (input D, C, R, output Q); FDPE_1 #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule
module \$_DFF_PN1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE(!R)); endmodule
module \$_DFF_PN1_ (input D, C, R, output Q); \$_DFF_PP1 _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
module \$_DFF_PP1_ (input D, C, R, output Q); FDPE #(.INIT(|0)) _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .CE(1'b1), .PRE( R)); endmodule
`endif

View file

@ -110,20 +110,20 @@ struct SynthXilinxPass : public Pass
log(" dffsr2dff\n");
log(" dff2dffe\n");
log(" opt -full\n");
log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v\n");
log(" techmap -map +/techmap.v -map +/xilinx/arith_map.v\n");
log(" opt -fast\n");
log("\n");
log(" map_cells:\n");
log(" techmap -map +/xilinx/cells_map.v\n");
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n");
log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n");
log(" clean\n");
log("\n");
log(" map_luts:\n");
log(" abc -luts 2:2,3,6:5,10,20 [-dff] (without '-vpr' only!)\n");
log(" abc -lut 5 [-dff] (with '-vpr' only!)\n");
log(" techmap -map +/techmap.v -map +/xilinx/ff_map.v t:$_DFF_?N?\n");
log(" abc -luts 2:2,3,6:5,10,20 [-dff]\n");
log(" clean\n");
log(" techmap -map +/xilinx/lut_map.v\n");
log(" techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v");
log(" dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT \\\n");
log(" -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n");
log("\n");
log(" check:\n");
log(" hierarchy -check\n");
@ -257,9 +257,9 @@ struct SynthXilinxPass : public Pass
Pass::call(design, "opt -full");
if (vpr) {
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v -D _EXPLICIT_CARRY");
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY");
} else {
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v -map +/xilinx/ff_map.v");
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/arith_map.v");
}
Pass::call(design, "hierarchy -check");
@ -269,16 +269,17 @@ struct SynthXilinxPass : public Pass
if (check_label(active, run_from, run_to, "map_cells"))
{
Pass::call(design, "techmap -map +/xilinx/cells_map.v");
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
Pass::call(design, "clean");
}
if (check_label(active, run_from, run_to, "map_luts"))
{
Pass::call(design, "techmap -map +/techmap.v -map +/xilinx/ff_map.v t:$_DFF_?N?");
Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : ""));
Pass::call(design, "clean");
Pass::call(design, "techmap -map +/xilinx/lut_map.v");
Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v");
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
}
if (check_label(active, run_from, run_to, "check"))

2
tests/aiger/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.log
*.out

6
tests/simple/retime.v Normal file
View file

@ -0,0 +1,6 @@
module retime_test(input clk, input [7:0] a, output z);
reg [7:0] ff = 8'hF5;
always @(posedge clk)
ff <= {ff[6:0], ^a};
assign z = ff[7];
endmodule