Skip to content

Commit

Permalink
Merge pull request YosysHQ#1724 from YosysHQ/eddie/abc9_specify
Browse files Browse the repository at this point in the history
abc9: auto-generate *.lut/*.box files and arrival/required times from specify entries
  • Loading branch information
eddiehung authored Mar 2, 2020
2 parents b1e248b + 090e545 commit 4f889b2
Show file tree
Hide file tree
Showing 43 changed files with 3,425 additions and 1,697 deletions.
20 changes: 7 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,25 +364,19 @@ Verilog Attributes and non-standard features
it as the external-facing pin of an I/O pad, and prevents ``iopadmap``
from inserting another pad cell on it.

- The module attribute ``abc9_box_id`` specifies a positive integer linking a
blackbox or whitebox definition to a corresponding entry in a `abc9`
box-file.
- The module attribute ``abc9_lut`` is an integer attribute indicating to
`abc9` that this module describes a LUT with an area cost of this value, and
propagation delays described using `specify` statements.

- The module attribute ``abc9_box`` is a boolean specifying a black/white-box
definition, with propagation delays described using `specify` statements, for
use by `abc9`.

- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and
carry-out (if output port) ports of a box. This information is necessary for
`abc9` to preserve the integrity of carry-chains. Specifying this attribute
onto a bus port will affect only its most significant bit.

- The output port attribute ``abc9_arrival`` specifies an integer, or a string
of space-separated integers to be used as the arrival time of this blackbox
port. It can be used, for example, to specify the clk-to-Q delay of a flip-
flop output for consideration during `abc9` techmapping.

- The input port attribute ``abc9_required`` specifies an integer, or a string
of space-separated integers to be used as the required time of this blackbox
port. It can be used, for example, to specify the setup-time of a flip-flop
input for consideration during `abc9` techmapping.

- The module attribute ``abc9_flop`` is a boolean marking the module as a
flip-flop. This allows `abc9` to analyse its contents in order to perform
sequential synthesis.
Expand Down
72 changes: 34 additions & 38 deletions backends/aiger/xaiger.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ inline static uint32_t bswap32(uint32_t x)
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/utils.h"
#include "kernel/timinginfo.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
Expand Down Expand Up @@ -184,9 +185,9 @@ struct XAigerWriter
}
}

dict<IdString,dict<IdString,std::vector<int>>> arrivals_cache;
TimingInfo timing;

for (auto cell : module->cells()) {
RTLIL::Module* inst_module = module->design->module(cell->type);
if (!cell->has_keep_attr()) {
if (cell->type == "$_NOT_")
{
Expand Down Expand Up @@ -227,8 +228,18 @@ struct XAigerWriter
continue;
}

if (inst_module) {
bool abc9_flop = false;
if (cell->type.in("$specify2", "$specify3", "$specrule"))
continue;
}

RTLIL::Module* inst_module = module->design->module(cell->type);
if (inst_module) {
IdString derived_type = inst_module->derive(module->design, cell->parameters);
inst_module = module->design->module(derived_type);
log_assert(inst_module);

bool abc9_flop = false;
if (!cell->has_keep_attr()) {
auto it = cell->attributes.find("\\abc9_box_seq");
if (it != cell->attributes.end()) {
int abc9_box_seq = it->second.as_int();
Expand All @@ -241,50 +252,34 @@ struct XAigerWriter
if (!abc9_flop)
continue;
}
}

auto &cell_arrivals = arrivals_cache[cell->type];
for (const auto &conn : cell->connections()) {
auto port_wire = inst_module->wire(conn.first);
if (!port_wire->port_output)
continue;

auto r = cell_arrivals.insert(conn.first);
auto &arrivals = r.first->second;
if (r.second) {
auto it = port_wire->attributes.find("\\abc9_arrival");
if (it == port_wire->attributes.end())
continue;
if (it->second.flags == 0)
arrivals.emplace_back(it->second.as_int());
else
for (const auto &tok : split_tokens(it->second.decode_string()))
arrivals.push_back(atoi(tok.c_str()));
}
if (!timing.count(derived_type))
timing.setup_module(inst_module);
auto &t = timing.at(derived_type).arrival;
for (const auto &conn : cell->connections()) {
auto port_wire = inst_module->wire(conn.first);
if (!port_wire->port_output)
continue;

if (arrivals.empty())
for (int i = 0; i < GetSize(conn.second); i++) {
auto d = t.at(TimingInfo::NameBit(conn.first,i), 0);
if (d == 0)
continue;

if (GetSize(arrivals) > 1 && GetSize(arrivals) != GetSize(port_wire))
log_error("%s.%s is %d bits wide but abc9_arrival = %s has %d value(s)!\n", log_id(cell->type), log_id(conn.first),
GetSize(port_wire), log_signal(it->second), GetSize(arrivals));

auto jt = arrivals.begin();
#ifndef NDEBUG
if (ys_debug(1)) {
static std::set<std::pair<IdString,IdString>> seen;
if (seen.emplace(cell->type, conn.first).second) log("%s.%s abc9_arrival = %d\n", log_id(cell->type), log_id(conn.first), *jt);
static std::set<std::tuple<IdString,IdString,int>> seen;
if (seen.emplace(derived_type, conn.first, i).second) log("%s.%s[%d] abc9_arrival = %d\n",
log_id(cell->type), log_id(conn.first), i, d);
}
#endif
for (auto bit : sigmap(conn.second)) {
arrival_times[bit] = *jt;
if (arrivals.size() > 1)
jt++;
}
arrival_times[conn.second[i]] = d;
}

if (abc9_flop)
continue;
}

if (abc9_flop)
continue;
}

bool cell_known = inst_module || cell->known();
Expand Down Expand Up @@ -661,6 +656,7 @@ struct XAigerWriter
write_s_buffer(0);
}

// Use arrival time from output of flop box
write_i_buffer(arrival_times.at(d, 0));
//write_o_buffer(0);
}
Expand Down
30 changes: 19 additions & 11 deletions frontends/ast/ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -939,14 +939,15 @@ RTLIL::Const AstNode::realAsConst(int width)
}

// create a new AstModule from an AST_MODULE AST node
static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL)
static AstModule* process_module(AstNode *ast, bool defer, AstNode *original_ast = NULL, bool quiet = false)
{
log_assert(ast->type == AST_MODULE || ast->type == AST_INTERFACE);

if (defer)
log("Storing AST representation for module `%s'.\n", ast->str.c_str());
else
else if (!quiet) {
log("Generating RTLIL representation for module `%s'.\n", ast->str.c_str());
}

current_module = new AstModule;
current_module->ast = NULL;
Expand Down Expand Up @@ -1484,14 +1485,16 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
// create a new parametric module (when needed) and return the name of the generated module - without support for interfaces
RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, bool /*mayfail*/)
{
bool quiet = lib || attributes.count(ID(blackbox)) || attributes.count(ID(whitebox));

AstNode *new_ast = NULL;
std::string modname = derive_common(design, parameters, &new_ast);
std::string modname = derive_common(design, parameters, &new_ast, quiet);

if (!design->has(modname)) {
new_ast->str = modname;
design->add(process_module(new_ast, false));
design->add(process_module(new_ast, false, NULL, quiet));
design->module(modname)->check();
} else {
} else if (!quiet) {
log("Found cached RTLIL representation for module `%s'.\n", modname.c_str());
}

Expand All @@ -1500,7 +1503,7 @@ RTLIL::IdString AstModule::derive(RTLIL::Design *design, dict<RTLIL::IdString, R
}

// create a new parametric module (when needed) and return the name of the generated module
std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out)
std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool quiet)
{
std::string stripped_name = name.str();

Expand All @@ -1516,13 +1519,15 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
para_counter++;
std::string para_id = child->str;
if (parameters.count(para_id) > 0) {
log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
if (!quiet)
log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
continue;
}
para_id = stringf("$%d", para_counter);
if (parameters.count(para_id) > 0) {
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
if (!quiet)
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
para_info += stringf("%s=%s", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
continue;
}
Expand All @@ -1539,7 +1544,8 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
if (design->has(modname))
return modname;

log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
if (!quiet)
log_header(design, "Executing AST frontend in derive mode using pre-parsed AST for module `%s'.\n", stripped_name.c_str());
loadconfig();

AstNode *new_ast = ast->clone();
Expand All @@ -1550,12 +1556,14 @@ std::string AstModule::derive_common(RTLIL::Design *design, dict<RTLIL::IdString
para_counter++;
std::string para_id = child->str;
if (parameters.count(para_id) > 0) {
log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
if (!quiet)
log("Parameter %s = %s\n", child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[child->str])));
goto rewrite_parameter;
}
para_id = stringf("$%d", para_counter);
if (parameters.count(para_id) > 0) {
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
if (!quiet)
log("Parameter %d (%s) = %s\n", para_counter, child->str.c_str(), log_signal(RTLIL::SigSpec(parameters[para_id])));
goto rewrite_parameter;
}
continue;
Expand Down
2 changes: 1 addition & 1 deletion frontends/ast/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ namespace AST
~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;
std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out);
std::string derive_common(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Const> parameters, AstNode **new_ast_out, bool quiet = false);
void reprocess_module(RTLIL::Design *design, dict<RTLIL::IdString, RTLIL::Module *> local_interfaces) YS_OVERRIDE;
RTLIL::Module *clone() const YS_OVERRIDE;
void loadconfig() const;
Expand Down
Loading

0 comments on commit 4f889b2

Please sign in to comment.