mirror of https://github.com/YosysHQ/yosys.git
write_xaiger2: further cleanup
This commit is contained in:
parent
a96cf8cc2b
commit
f09afcf581
|
|
@ -21,6 +21,9 @@
|
|||
// - gracefully handling inout ports (an error message probably)
|
||||
// - undriven wires
|
||||
// - zero-width operands
|
||||
// - decide how to unify this with cellaigs
|
||||
// - break up Index into something smaller
|
||||
// - (C++20) remove snprintf-into-std::ostream weirdness
|
||||
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/newcelltypes.h"
|
||||
|
|
@ -179,6 +182,9 @@ struct Index {
|
|||
} else {
|
||||
// AigMaker::node2index
|
||||
|
||||
// In XAIGER, the ordering of inputs is used to distinguish between AND
|
||||
// and XOR gates. AND gates have their first input literal be larger
|
||||
// than their second, and vice-versa for XORs.
|
||||
if (a < b) std::swap(a, b);
|
||||
auto pair = std::make_pair(a, b);
|
||||
|
||||
|
|
@ -531,7 +537,7 @@ struct Index {
|
|||
Design *design = index.design;
|
||||
auto &minfo = leaf_minfo(index);
|
||||
if (!minfo.suboffsets.count(cell))
|
||||
log_error("Reached unsupport cell %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(cell->module));
|
||||
log_error("Reached unsupported cell %s (%s in %s)\n", log_id(cell->type), log_id(cell), log_id(cell->module));
|
||||
Module *def = design->module(cell->type);
|
||||
log_assert(def);
|
||||
levels.push_back(Level(index.modules.at(def), cell));
|
||||
|
|
@ -550,13 +556,13 @@ struct Index {
|
|||
{
|
||||
std::string ret;
|
||||
bool first = true;
|
||||
for (auto pair : levels) {
|
||||
for (auto [minfo, cell] : levels) {
|
||||
if (!first)
|
||||
ret += ".";
|
||||
if (!pair.second)
|
||||
ret += RTLIL::unescape_id(pair.first.module->name);
|
||||
if (!cell)
|
||||
ret += RTLIL::unescape_id(minfo.module->name);
|
||||
else
|
||||
ret += RTLIL::unescape_id(pair.second->name);
|
||||
ret += RTLIL::unescape_id(cell->name);
|
||||
first = false;
|
||||
}
|
||||
return ret;
|
||||
|
|
@ -565,8 +571,8 @@ struct Index {
|
|||
int hash() const
|
||||
{
|
||||
int hash = 0;
|
||||
for (auto pair : levels)
|
||||
hash += (uintptr_t) pair.second;
|
||||
for (auto [_, cell] : levels)
|
||||
hash += (uintptr_t) cell;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
@ -575,9 +581,12 @@ struct Index {
|
|||
if (levels.size() != other.levels.size())
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < levels.size(); i++)
|
||||
if (levels[i].second != other.levels[i].second)
|
||||
for (int i = 0; i < levels.size(); i++) {
|
||||
auto* cell = levels[i].second;
|
||||
auto* other_cell = other.levels[i].second;
|
||||
if (cell != other_cell)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -740,6 +749,9 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
nands++;
|
||||
lit_counter += 2;
|
||||
|
||||
// In XAIGER, the ordering of inputs is used to distinguish between AND
|
||||
// and XOR gates. AND gates have their first input literal be larger
|
||||
// than their second, and vice-versa for XORs.
|
||||
if (a < b) std::swap(a, b);
|
||||
encode(out - a);
|
||||
encode(a - b);
|
||||
|
|
@ -756,7 +768,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
log_assert(lit_counter == (Lit) (ninputs + nlatches + nands) * 2 + 2);
|
||||
|
||||
char buf[128];
|
||||
snprintf(buf, sizeof(buf) - 1, "aig %08d %08d %08d %08d %08d\n",
|
||||
snprintf(buf, sizeof(buf), "aig %08d %08d %08d %08d %08d\n",
|
||||
ninputs + nlatches + nands, ninputs, nlatches, noutputs, nands);
|
||||
f->write(buf, strlen(buf));
|
||||
}
|
||||
|
|
@ -773,8 +785,9 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
log_assert(w);
|
||||
if (w->port_input && !w->port_output)
|
||||
for (int i = 0; i < w->width; i++) {
|
||||
pi_literal(SigBit(w, i)) = lit_counter;
|
||||
inputs.push_back(SigBit(w, i));
|
||||
auto bit = SigBit(w, i);
|
||||
pi_literal(bit) = lit_counter;
|
||||
inputs.push_back(bit);
|
||||
lit_counter += 2;
|
||||
ninputs++;
|
||||
}
|
||||
|
|
@ -791,7 +804,7 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
for (auto bit : SigSpec(w)) {
|
||||
(void) bit;
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", 0);
|
||||
snprintf(buf, sizeof(buf), "%08d\n", 0);
|
||||
f->write(buf, strlen(buf));
|
||||
noutputs++;
|
||||
}
|
||||
|
|
@ -804,16 +817,19 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
for (auto w : top->wires())
|
||||
if (w->port_output) {
|
||||
for (auto bit : SigSpec(w))
|
||||
// Each call to eval_po eventually reaches emit_gate and
|
||||
// encode which writes to f.
|
||||
outputs.push_back({bit, eval_po(bit)});
|
||||
}
|
||||
|
||||
auto data_end = f->tellp();
|
||||
|
||||
// revisit header and the list of outputs
|
||||
f->seekp(file_start);
|
||||
write_header();
|
||||
for (auto pair : outputs) {
|
||||
for (auto [_, po] : outputs) {
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", pair.second);
|
||||
snprintf(buf, sizeof(buf), "%08d\n", po);
|
||||
f->write(buf, strlen(buf));
|
||||
}
|
||||
// double check we arrived at the same offset for the
|
||||
|
|
@ -822,12 +838,13 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
|
||||
f->seekp(data_end);
|
||||
int i = 0;
|
||||
for (auto pair : outputs) {
|
||||
if (SigSpec(pair.first).is_wire()) {
|
||||
for (auto [bit, _] : outputs) {
|
||||
if (SigSpec(bit).is_wire()) {
|
||||
// primary output symbol
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf) - 1, "o%d ", i);
|
||||
snprintf(buf, sizeof(buf), "o%d ", i);
|
||||
f->write(buf, strlen(buf));
|
||||
std::string name = RTLIL::unescape_id(pair.first.wire->name);
|
||||
std::string name = RTLIL::unescape_id(bit.wire->name);
|
||||
f->write(name.data(), name.size());
|
||||
f->put('\n');
|
||||
}
|
||||
|
|
@ -836,8 +853,9 @@ struct AigerWriter : Index<AigerWriter, unsigned int, 0, 1> {
|
|||
i = 0;
|
||||
for (auto bit : inputs) {
|
||||
if (SigSpec(bit).is_wire()) {
|
||||
// primary input symbol
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf) - 1, "i%d ", i);
|
||||
snprintf(buf, sizeof(buf), "i%d ", i);
|
||||
f->write(buf, strlen(buf));
|
||||
std::string name = RTLIL::unescape_id(bit.wire->name);
|
||||
f->write(name.data(), name.size());
|
||||
|
|
@ -1242,29 +1260,29 @@ struct XAigerWriter : AigerWriter {
|
|||
reset_counters();
|
||||
|
||||
for (auto w : top->wires())
|
||||
if (w->port_input && !w->port_output)
|
||||
for (int i = 0; i < w->width; i++)
|
||||
ensure_pi(SigBit(w, i));
|
||||
if (w->port_input && !w->port_output)
|
||||
for (int i = 0; i < w->width; i++)
|
||||
ensure_pi(SigBit(w, i));
|
||||
|
||||
int proper_po_num = 0;
|
||||
for (auto w : top->wires())
|
||||
if (w->port_output)
|
||||
proper_po_num += w->width;
|
||||
if (w->port_output)
|
||||
proper_po_num += w->width;
|
||||
|
||||
prep_boxes(proper_po_num);
|
||||
for (auto w : top->wires())
|
||||
if (w->port_output)
|
||||
for (int i = 0; i < w->width; i++) {
|
||||
// When a module output is directly driven by an opaque box, we
|
||||
// don't emit it to the mapping file to aid re-integration, but we
|
||||
// do emit a proper PO.
|
||||
if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) {
|
||||
map_file << "po " << proper_pos_counter << " " << i
|
||||
<< " " << w->name.c_str() << "\n";
|
||||
}
|
||||
proper_pos_counter++;
|
||||
pos.push_back(std::make_pair(SigBit(w, i), HierCursor{}));
|
||||
}
|
||||
if (w->port_output)
|
||||
for (int i = 0; i < w->width; i++) {
|
||||
// When a module output is directly driven by an opaque box, we
|
||||
// don't emit it to the mapping file to aid re-integration, but we
|
||||
// do emit a proper PO.
|
||||
if (map_file.is_open() && !driven_by_opaque_box.count(SigBit(w, i))) {
|
||||
map_file << "po " << proper_pos_counter << " " << i
|
||||
<< " " << w->name.c_str() << "\n";
|
||||
}
|
||||
proper_pos_counter++;
|
||||
pos.push_back(std::make_pair(SigBit(w, i), HierCursor{}));
|
||||
}
|
||||
|
||||
this->f = f;
|
||||
// start with the header
|
||||
|
|
@ -1274,7 +1292,7 @@ struct XAigerWriter : AigerWriter {
|
|||
// insert padding where output literals will go (once known)
|
||||
for (auto _ : pos) {
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", 0);
|
||||
snprintf(buf, sizeof(buf), "%08d\n", 0);
|
||||
f->write(buf, strlen(buf));
|
||||
}
|
||||
auto data_start = f->tellp();
|
||||
|
|
@ -1291,35 +1309,36 @@ struct XAigerWriter : AigerWriter {
|
|||
write_header();
|
||||
for (auto lit : outlits) {
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf) - 1, "%08d\n", lit);
|
||||
snprintf(buf, sizeof(buf), "%08d\n", lit);
|
||||
f->write(buf, strlen(buf));
|
||||
}
|
||||
// double check we arrived at the same offset for the
|
||||
// main data section
|
||||
log_assert(data_start == f->tellp());
|
||||
|
||||
// extensions
|
||||
// XAIGER extensions
|
||||
f->seekp(0, std::ios::end);
|
||||
|
||||
f->put('c');
|
||||
f->put('c'); // 'c': comment (marks beginning of extensions)
|
||||
|
||||
// insert empty 'r' and 's' sections (abc crashes if we provide 'a' without those)
|
||||
f->put('r');
|
||||
write_be32(*f, 4);
|
||||
write_be32(*f, 0);
|
||||
f->put('s');
|
||||
write_be32(*f, 4);
|
||||
write_be32(*f, 0);
|
||||
f->put('r'); // 'r': register classes
|
||||
write_be32(*f, 4); // length in bytes
|
||||
write_be32(*f, 0); // no register classes
|
||||
|
||||
f->put('h');
|
||||
f->put('s'); // 's': register initial values
|
||||
write_be32(*f, 4); // length in bytes
|
||||
write_be32(*f, 0); // no register initial values
|
||||
|
||||
f->put('h'); // 'h': hierarchy information
|
||||
// TODO: get rid of std::string copy
|
||||
std::string h_buffer_str = h_buffer.str();
|
||||
write_be32(*f, h_buffer_str.size());
|
||||
f->write(h_buffer_str.data(), h_buffer_str.size());
|
||||
write_be32(*f, h_buffer_str.size()); // length in bytes
|
||||
f->write(h_buffer_str.data(), h_buffer_str.size()); // data
|
||||
|
||||
#if 1
|
||||
f->put('a');
|
||||
write_be32(*f, 0); // size to be filled later
|
||||
f->put('a'); // 'a': additional AIG (used for holes)
|
||||
write_be32(*f, 0); // length in bytes (to be filled later)
|
||||
auto holes_aiger_start = f->tellp();
|
||||
{
|
||||
AigerWriter holes_writer;
|
||||
|
|
@ -1331,7 +1350,7 @@ struct XAigerWriter : AigerWriter {
|
|||
auto holes_aiger_size = f->tellp() - holes_aiger_start;
|
||||
f->seekp(holes_aiger_start, std::ios::beg);
|
||||
f->seekp(-4, std::ios::cur);
|
||||
write_be32(*f, holes_aiger_size);
|
||||
write_be32(*f, holes_aiger_size); // length in bytes
|
||||
#endif
|
||||
f->seekp(0, std::ios::end);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue