mirror of https://github.com/YosysHQ/yosys.git
aiger2: Adjust hierarchy/port handling
This commit is contained in:
parent
2a3e907da8
commit
ea765686b6
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
// TODOs:
|
// TODOs:
|
||||||
// - gracefully handling inout ports (an error message probably)
|
// - gracefully handling inout ports (an error message probably)
|
||||||
|
// - undriven wires
|
||||||
|
|
||||||
#include "kernel/register.h"
|
#include "kernel/register.h"
|
||||||
#include "kernel/celltypes.h"
|
#include "kernel/celltypes.h"
|
||||||
|
@ -56,6 +57,7 @@ struct Index {
|
||||||
int len;
|
int len;
|
||||||
dict<Wire *, int> windices;
|
dict<Wire *, int> windices;
|
||||||
dict<Cell *, int> suboffsets;
|
dict<Cell *, int> suboffsets;
|
||||||
|
pool<Cell *> found_blackboxes;
|
||||||
|
|
||||||
bool indexing = false;
|
bool indexing = false;
|
||||||
bool indexed = false;
|
bool indexed = false;
|
||||||
|
@ -73,6 +75,10 @@ struct Index {
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool flatten = false;
|
||||||
|
bool inline_whiteboxes = false;
|
||||||
|
bool allow_blackboxes = false;
|
||||||
|
|
||||||
int index_module(RTLIL::Module *m)
|
int index_module(RTLIL::Module *m)
|
||||||
{
|
{
|
||||||
ModuleInfo &info = modules[m];
|
ModuleInfo &info = modules[m];
|
||||||
|
@ -91,11 +97,21 @@ struct Index {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Module *submodule = m->design->module(cell->type);
|
Module *submodule = m->design->module(cell->type);
|
||||||
if (!submodule || submodule->get_blackbox_attribute())
|
|
||||||
log_error("Unsupported cell type: %s (%s in %s)\n",
|
if (submodule && flatten &&
|
||||||
log_id(cell->type), log_id(cell), log_id(m));
|
!submodule->get_bool_attribute(ID::keep_hierarchy) &&
|
||||||
info.suboffsets[cell] = pos;
|
!submodule->get_blackbox_attribute(inline_whiteboxes)) {
|
||||||
pos += index_module(submodule);
|
info.suboffsets[cell] = pos;
|
||||||
|
pos += index_module(submodule);
|
||||||
|
} else {
|
||||||
|
if (allow_blackboxes) {
|
||||||
|
info.found_blackboxes.insert(cell);
|
||||||
|
} else {
|
||||||
|
if (!submodule || submodule->get_blackbox_attribute())
|
||||||
|
log_error("Unsupported cell type: %s (%s in %s)\n",
|
||||||
|
log_id(cell->type), log_id(cell), log_id(m));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info.len = pos;
|
info.len = pos;
|
||||||
|
@ -429,30 +445,36 @@ struct Index {
|
||||||
std::vector<Level> levels;
|
std::vector<Level> levels;
|
||||||
int instance_offset = 0;
|
int instance_offset = 0;
|
||||||
|
|
||||||
HierCursor(ModuleInfo &top)
|
HierCursor()
|
||||||
{
|
{
|
||||||
levels.push_back(Level(top, nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleInfo ¤t_minfo()
|
ModuleInfo &leaf_minfo(Index &index)
|
||||||
{
|
{
|
||||||
log_assert(!levels.empty());
|
if (levels.empty())
|
||||||
return levels.back().first;
|
return *index.top_minfo;
|
||||||
|
else
|
||||||
|
return levels.back().first;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitwire_index(SigBit bit)
|
Module *leaf_module(Index &index)
|
||||||
|
{
|
||||||
|
return leaf_minfo(index).module;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bitwire_index(Index &index, SigBit bit)
|
||||||
{
|
{
|
||||||
log_assert(bit.wire != nullptr);
|
log_assert(bit.wire != nullptr);
|
||||||
return instance_offset + current_minfo().windices[bit.wire] + bit.offset;
|
return instance_offset + leaf_minfo(index).windices[bit.wire] + bit.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cell *exit()
|
Cell *exit(Index &index)
|
||||||
{
|
{
|
||||||
log_assert(levels.size() > 1);
|
log_assert(!levels.empty());
|
||||||
Cell *instance = levels.back().second;
|
Cell *instance = levels.back().second;
|
||||||
|
|
||||||
levels.pop_back();
|
levels.pop_back();
|
||||||
instance_offset -= current_minfo().suboffsets.at(instance);
|
instance_offset -= leaf_minfo(index).suboffsets.at(instance);
|
||||||
|
|
||||||
// return the instance we just exited
|
// return the instance we just exited
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -461,7 +483,7 @@ struct Index {
|
||||||
Module *enter(Index &index, Cell *cell)
|
Module *enter(Index &index, Cell *cell)
|
||||||
{
|
{
|
||||||
Design *design = index.design;
|
Design *design = index.design;
|
||||||
auto &minfo = current_minfo();
|
auto &minfo = leaf_minfo(index);
|
||||||
log_assert(minfo.suboffsets.count(cell));
|
log_assert(minfo.suboffsets.count(cell));
|
||||||
Module *def = design->module(cell->type);
|
Module *def = design->module(cell->type);
|
||||||
log_assert(def);
|
log_assert(def);
|
||||||
|
@ -471,6 +493,47 @@ struct Index {
|
||||||
// return the module definition we just entered
|
// return the module definition we just entered
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_top()
|
||||||
|
{
|
||||||
|
return levels.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string path()
|
||||||
|
{
|
||||||
|
std::string ret;
|
||||||
|
bool first = true;
|
||||||
|
for (auto pair : levels) {
|
||||||
|
if (!first)
|
||||||
|
ret += ".";
|
||||||
|
if (!pair.second)
|
||||||
|
ret += RTLIL::unescape_id(pair.first.module->name);
|
||||||
|
else
|
||||||
|
ret += RTLIL::unescape_id(pair.second->name);
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hash() const
|
||||||
|
{
|
||||||
|
int hash = 0;
|
||||||
|
for (auto pair : levels)
|
||||||
|
hash += (uintptr_t) pair.second;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const HierCursor &other) const
|
||||||
|
{
|
||||||
|
if (levels.size() != other.levels.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0; i < levels.size(); i++)
|
||||||
|
if (levels[i].second != other.levels[i].second)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Lit visit(HierCursor &cursor, SigBit bit)
|
Lit visit(HierCursor &cursor, SigBit bit)
|
||||||
|
@ -484,7 +547,7 @@ struct Index {
|
||||||
log_error("Unhandled state %s\n", log_signal(bit));
|
log_error("Unhandled state %s\n", log_signal(bit));
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx = cursor.bitwire_index(bit);
|
int idx = cursor.bitwire_index(*this, bit);
|
||||||
if (lits[idx] != Writer::EMPTY_LIT) {
|
if (lits[idx] != Writer::EMPTY_LIT) {
|
||||||
// literal already assigned
|
// literal already assigned
|
||||||
return lits[idx];
|
return lits[idx];
|
||||||
|
@ -510,16 +573,15 @@ struct Index {
|
||||||
bit.offset, log_id(portname), log_id(driver), log_id(def), w->width);
|
bit.offset, log_id(portname), log_id(driver), log_id(def), w->width);
|
||||||
ret = visit(cursor, SigBit(w, bit.offset));
|
ret = visit(cursor, SigBit(w, bit.offset));
|
||||||
}
|
}
|
||||||
cursor.exit();
|
cursor.exit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// a module input: we cannot be the top module, otherwise
|
// a module input: we cannot be the top module, otherwise
|
||||||
// the branch for pre-existing literals would have been taken
|
// the branch for pre-existing literals would have been taken
|
||||||
log_assert(cursor.levels.size() > 1);
|
log_assert(!cursor.is_top());
|
||||||
|
|
||||||
// step into the upper module
|
// step into the upper module
|
||||||
Cell *instance = cursor.exit();
|
Cell *instance = cursor.exit(*this);
|
||||||
{
|
{
|
||||||
IdString portname = bit.wire->name;
|
IdString portname = bit.wire->name;
|
||||||
if (!instance->hasPort(portname))
|
if (!instance->hasPort(portname))
|
||||||
|
@ -538,23 +600,54 @@ struct Index {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_top_port(SigBit bit, Lit lit)
|
Lit &pi_literal(SigBit bit, HierCursor *cursor=nullptr)
|
||||||
{
|
{
|
||||||
log_assert(bit.wire);
|
log_assert(bit.wire);
|
||||||
log_assert(bit.wire->module == top);
|
|
||||||
log_assert(bit.wire->port_input);
|
|
||||||
|
|
||||||
lits[top_minfo->windices[bit.wire] + bit.offset] = lit;
|
if (!cursor) {
|
||||||
|
log_assert(bit.wire->module == top);
|
||||||
|
log_assert(bit.wire->port_input);
|
||||||
|
return lits[top_minfo->windices[bit.wire] + bit.offset];
|
||||||
|
} else {
|
||||||
|
log_assert(bit.wire->module == cursor->leaf_module(*this));
|
||||||
|
return lits[cursor->bitwire_index(*this, bit)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Lit get_top_port(SigBit bit)
|
Lit eval_po(SigBit bit, HierCursor *cursor=nullptr)
|
||||||
{
|
{
|
||||||
HierCursor cursor(*top_minfo);
|
Lit ret;
|
||||||
Lit ret = visit(cursor, bit);
|
if (!cursor) {
|
||||||
log_assert(cursor.levels.size() == 1);
|
HierCursor cursor_;
|
||||||
log_assert(cursor.instance_offset == 0);
|
ret = visit(cursor_, bit);
|
||||||
|
log_assert(cursor_.is_top());
|
||||||
|
log_assert(cursor_.instance_offset == 0);
|
||||||
|
} else {
|
||||||
|
ret = visit(*cursor, bit);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visit_hierarchy(std::function<void(HierCursor&)> f,
|
||||||
|
HierCursor &cursor)
|
||||||
|
{
|
||||||
|
f(cursor);
|
||||||
|
|
||||||
|
ModuleInfo &minfo = cursor.leaf_minfo(*this);
|
||||||
|
for (auto cell : minfo.module->cells()) {
|
||||||
|
if (minfo.suboffsets.count(cell)) {
|
||||||
|
cursor.enter(*this, cell);
|
||||||
|
visit_hierarchy(f, cursor);
|
||||||
|
cursor.exit(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void visit_hierarchy(std::function<void(HierCursor&)> f)
|
||||||
|
{
|
||||||
|
HierCursor cursor;
|
||||||
|
visit_hierarchy(f, cursor);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AigerWriter : Index<AigerWriter, unsigned int> {
|
struct AigerWriter : Index<AigerWriter, unsigned int> {
|
||||||
|
@ -616,20 +709,25 @@ struct AigerWriter : Index<AigerWriter, unsigned int> {
|
||||||
|
|
||||||
// populate inputs
|
// populate inputs
|
||||||
std::vector<SigBit> inputs;
|
std::vector<SigBit> inputs;
|
||||||
for (auto w : top->wires())
|
for (auto id : top->ports) {
|
||||||
|
Wire *w = top->wire(id);
|
||||||
|
log_assert(w);
|
||||||
if (w->port_input)
|
if (w->port_input)
|
||||||
for (int i = 0; i < w->width; i++) {
|
for (int i = 0; i < w->width; i++) {
|
||||||
set_top_port(SigBit(w, i), lit_counter);
|
pi_literal(SigBit(w, i)) = lit_counter;
|
||||||
inputs.push_back(SigBit(w, i));
|
inputs.push_back(SigBit(w, i));
|
||||||
lit_counter += 2;
|
lit_counter += 2;
|
||||||
ninputs++;
|
ninputs++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this->f = f;
|
this->f = f;
|
||||||
// start with the header
|
// start with the header
|
||||||
write_header();
|
write_header();
|
||||||
// insert padding where output literals will go (once known)
|
// insert padding where output literals will go (once known)
|
||||||
for (auto w : top->wires())
|
for (auto id : top->ports) {
|
||||||
|
Wire *w = top->wire(id);
|
||||||
|
log_assert(w);
|
||||||
if (w->port_output) {
|
if (w->port_output) {
|
||||||
for (auto bit : SigSpec(w)) {
|
for (auto bit : SigSpec(w)) {
|
||||||
(void) bit;
|
(void) bit;
|
||||||
|
@ -639,6 +737,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int> {
|
||||||
noutputs++;
|
noutputs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
auto data_start = f->tellp();
|
auto data_start = f->tellp();
|
||||||
|
|
||||||
// now the guts
|
// now the guts
|
||||||
|
@ -646,7 +745,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int> {
|
||||||
for (auto w : top->wires())
|
for (auto w : top->wires())
|
||||||
if (w->port_output) {
|
if (w->port_output) {
|
||||||
for (auto bit : SigSpec(w))
|
for (auto bit : SigSpec(w))
|
||||||
outputs.push_back({bit, get_top_port(bit)});
|
outputs.push_back({bit, eval_po(bit)});
|
||||||
}
|
}
|
||||||
auto data_end = f->tellp();
|
auto data_end = f->tellp();
|
||||||
|
|
||||||
|
@ -749,6 +848,8 @@ struct Aiger2Backend : Backend {
|
||||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||||
if (args[argidx] == "-strash")
|
if (args[argidx] == "-strash")
|
||||||
writer.strashing = true;
|
writer.strashing = true;
|
||||||
|
else if (args[argidx] == "-flatten")
|
||||||
|
writer.flatten = true;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -791,12 +892,12 @@ struct AIGCounter : Index<AIGCounter, int> {
|
||||||
for (auto w : top->wires())
|
for (auto w : top->wires())
|
||||||
if (w->port_input)
|
if (w->port_input)
|
||||||
for (int i = 0; i < w->width; i++)
|
for (int i = 0; i < w->width; i++)
|
||||||
set_top_port(SigBit(w, i), ++nvars);
|
pi_literal(SigBit(w, i)) = ++nvars;
|
||||||
|
|
||||||
for (auto w : top->wires())
|
for (auto w : top->wires())
|
||||||
if (w->port_output) {
|
if (w->port_output) {
|
||||||
for (auto bit : SigSpec(w))
|
for (auto bit : SigSpec(w))
|
||||||
(void) get_top_port(bit);
|
(void) eval_po(bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -808,10 +909,12 @@ struct AigsizePass : Pass {
|
||||||
log_header(design, "Executing AIGSIZE pass. (size design AIG)\n");
|
log_header(design, "Executing AIGSIZE pass. (size design AIG)\n");
|
||||||
|
|
||||||
size_t argidx;
|
size_t argidx;
|
||||||
AIGCounter counter;
|
AIGCounter writer;
|
||||||
for (argidx = 1; argidx < args.size(); argidx++) {
|
for (argidx = 1; argidx < args.size(); argidx++) {
|
||||||
if (args[argidx] == "-strash")
|
if (args[argidx] == "-strash")
|
||||||
counter.strashing = true;
|
writer.strashing = true;
|
||||||
|
else if (args[argidx] == "-flatten")
|
||||||
|
writer.flatten = true;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -823,9 +926,9 @@ struct AigsizePass : Pass {
|
||||||
log_cmd_error("No top module selected\n");
|
log_cmd_error("No top module selected\n");
|
||||||
|
|
||||||
design->bufNormalize(true);
|
design->bufNormalize(true);
|
||||||
counter.setup(top);
|
writer.setup(top);
|
||||||
counter.count();
|
writer.count();
|
||||||
log("Counted %d gates\n", counter.ngates);
|
log("Counted %d gates\n", writer.ngates);
|
||||||
|
|
||||||
// we are leaving the sacred land, un-bufnormalize
|
// we are leaving the sacred land, un-bufnormalize
|
||||||
// (if not, this will lead to bugs: the buf-normalized
|
// (if not, this will lead to bugs: the buf-normalized
|
||||||
|
|
|
@ -158,7 +158,7 @@ copy test gold
|
||||||
flatten gold
|
flatten gold
|
||||||
techmap submodule1
|
techmap submodule1
|
||||||
select test
|
select test
|
||||||
write_aiger2 aiger2_ops.aig
|
write_aiger2 -flatten aiger2_ops.aig
|
||||||
select -clear
|
select -clear
|
||||||
delete test
|
delete test
|
||||||
read_aiger -module_name test aiger2_ops.aig
|
read_aiger -module_name test aiger2_ops.aig
|
||||||
|
|
Loading…
Reference in New Issue