mirror of
https://github.com/YosysHQ/yosys.git
synced 2026-10-06 10:03:36 +02:00
@@ -998,7 +998,7 @@ struct XAigerWriter : AigerWriter {
|
||||
if (map_file.is_open() && !box_port) {
|
||||
log_assert(cursor.is_top()); // TODO
|
||||
driven_by_opaque_box.insert(bit);
|
||||
map_file << "pi " << pis.size() - 1 << " " << bit.offset
|
||||
map_file << "input " << pis.size() - 1 << " " << bit.offset
|
||||
<< " " << bit.wire->name.c_str() << "\n";
|
||||
}
|
||||
} else {
|
||||
@@ -1273,11 +1273,8 @@ struct XAigerWriter : AigerWriter {
|
||||
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
|
||||
if (map_file.is_open()) {
|
||||
map_file << "output " << proper_pos_counter << " " << i
|
||||
<< " " << w->name.c_str() << "\n";
|
||||
}
|
||||
proper_pos_counter++;
|
||||
@@ -1502,7 +1499,7 @@ struct XAiger2Backend : Backend {
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log("\n");
|
||||
log(" -map2 <file>\n");
|
||||
log(" write a map2 file which 'read_xaiger2 -sc_mapping' can read to\n");
|
||||
log(" write a map2 file which 'abc_ops_reintegrate' can read to\n");
|
||||
log(" reintegrate a mapping\n");
|
||||
log(" (conflicts with -flatten)\n");
|
||||
log("\n");
|
||||
|
||||
@@ -128,7 +128,6 @@ Other built-in ``read_*`` commands
|
||||
- :cmd:title:`read_blif`
|
||||
- :cmd:title:`read_json`
|
||||
- :cmd:title:`read_liberty`
|
||||
- :cmd:title:`read_xaiger2`
|
||||
|
||||
.. TODO:: does `write_file` count?
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
add_subdirectory(aiger)
|
||||
add_subdirectory(aiger2)
|
||||
add_subdirectory(ast)
|
||||
add_subdirectory(blif)
|
||||
add_subdirectory(json)
|
||||
|
||||
@@ -480,19 +480,22 @@ void AigerReader::parse_xaiger()
|
||||
mapping_cell.type = RTLIL::escape_id(cellName);
|
||||
mapping_cell.out = RTLIL::escape_id(outPinName);
|
||||
|
||||
auto module = design->addModule(RTLIL::escape_id(cellName));
|
||||
module->set_bool_attribute(ID::blackbox);
|
||||
module->addWire(RTLIL::escape_id(outPinName))->port_output = true;
|
||||
|
||||
for (unsigned j = 0; j < inPinNum; ++j) {
|
||||
auto inPinName = std::string{};
|
||||
std::getline(f, inPinName, '\0');
|
||||
log_debug2("M: inPinName=%s\n", inPinName);
|
||||
mapping_cell.ins.push_back(RTLIL::escape_id(inPinName));
|
||||
module->addWire(RTLIL::escape_id(inPinName))->port_input = true;
|
||||
}
|
||||
|
||||
module->fixup_ports();
|
||||
if (!design->module(mapping_cell.type)) {
|
||||
auto module = design->addModule(mapping_cell.type);
|
||||
module->set_bool_attribute(ID::blackbox);
|
||||
module->addWire(mapping_cell.out)->port_output = true;
|
||||
for (unsigned j = 0; j < inPinNum; ++j) {
|
||||
module->addWire(mapping_cell.ins.at(j))->port_input = true;
|
||||
}
|
||||
module->fixup_ports();
|
||||
}
|
||||
|
||||
mapping_cells.push_back(std::move(mapping_cell));
|
||||
}
|
||||
@@ -522,6 +525,7 @@ void AigerReader::parse_xaiger()
|
||||
}
|
||||
|
||||
RTLIL::Cell *cell = module->addCell(stringf("$sc$aiger%d$%d", aiger_autoidx, rootNodeID), mapping_cell.type);
|
||||
cell->set_bool_attribute(ID::abc9_cell);
|
||||
cell->setPort(mapping_cell.out, output_sig);
|
||||
|
||||
for (unsigned j = 0; j < mapping_cell.ins.size(); ++j) {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
yosys_frontend(xaiger2
|
||||
xaiger.cc
|
||||
)
|
||||
@@ -1,470 +0,0 @@
|
||||
/*
|
||||
* yosys -- Yosys Open SYnthesis Suite
|
||||
*
|
||||
* Copyright (C) Martin Povišer <[email protected]>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "kernel/register.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
uint32_t read_be32(std::istream &f) {
|
||||
return ((uint32_t) f.get() << 24) |
|
||||
((uint32_t) f.get() << 16) |
|
||||
((uint32_t) f.get() << 8) | (uint32_t) f.get();
|
||||
}
|
||||
|
||||
IdString read_idstring(std::istream &f)
|
||||
{
|
||||
std::string str;
|
||||
std::getline(f, str, '\0');
|
||||
if (!f.good())
|
||||
log_error("failed to read string\n");
|
||||
return RTLIL::escape_id(str);
|
||||
}
|
||||
|
||||
struct Xaiger2Frontend : public Frontend {
|
||||
Xaiger2Frontend() : Frontend("xaiger2", "(experimental) read XAIGER file")
|
||||
{
|
||||
experimental();
|
||||
}
|
||||
|
||||
void help() override
|
||||
{
|
||||
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
|
||||
log("\n");
|
||||
log(" read_xaiger2 -sc_mapping [options] <filename>\n");
|
||||
log("\n");
|
||||
log("Read a standard cell mapping from a XAIGER file into an existing module.\n");
|
||||
log("\n");
|
||||
log(" -module_name <name>\n");
|
||||
log(" name of the target module\n");
|
||||
log("\n");
|
||||
log(" -map2 <filename>\n");
|
||||
log(" read file with symbol information\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void read_sc_mapping(std::istream *&f, std::string filename, std::vector<std::string> args, Design *design)
|
||||
{
|
||||
IdString module_name;
|
||||
std::string map_filename;
|
||||
|
||||
size_t argidx;
|
||||
for (argidx = 2; argidx < args.size(); argidx++) {
|
||||
std::string arg = args[argidx];
|
||||
if (arg == "-module_name" && argidx + 1 < args.size()) {
|
||||
module_name = RTLIL::escape_id(args[++argidx]);
|
||||
continue;
|
||||
}
|
||||
if (arg == "-map2" && argidx + 1 < args.size()) {
|
||||
map_filename = args[++argidx];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(f, filename, args, argidx, true);
|
||||
|
||||
if (map_filename.empty())
|
||||
log_error("A '-map2' argument is required\n");
|
||||
if (module_name.empty())
|
||||
log_error("A '-module_name' argument is required\n");
|
||||
|
||||
Module *module = design->module(module_name);
|
||||
if (!module)
|
||||
log_error("Module '%s' not found\n", module_name.unescape());
|
||||
|
||||
std::ifstream map_file;
|
||||
map_file.open(map_filename);
|
||||
if (!map_file)
|
||||
log_error("Failed to open map file '%s'\n", map_filename);
|
||||
|
||||
unsigned int M, I, L, O, A;
|
||||
std::string header;
|
||||
if (!(*f >> header >> M >> I >> L >> O >> A) || header != "aig")
|
||||
log_error("Bad header\n");
|
||||
std::string line;
|
||||
std::getline(*f, line);
|
||||
log_debug("M=%u I=%u L=%u O=%u A=%u\n", M, I, L, O, A);
|
||||
|
||||
if (L != 0)
|
||||
log_error("Latches unsupported\n");
|
||||
if (I + L + A != M)
|
||||
log_error("Inconsistent header\n");
|
||||
|
||||
std::vector<int> outputs;
|
||||
for (int i = 0; i < (int) O; i++) {
|
||||
int po;
|
||||
*f >> po;
|
||||
int c = f->get();
|
||||
log_assert(c == '\n');
|
||||
outputs.push_back(po);
|
||||
}
|
||||
|
||||
std::vector<std::pair<Cell *, Module *>> boxes;
|
||||
std::vector<bool> retained_boxes;
|
||||
std::vector<SigBit> bits(2 + 2*M, RTLIL::Sm);
|
||||
bits[0] = RTLIL::S0;
|
||||
bits[1] = RTLIL::S1;
|
||||
|
||||
std::string type;
|
||||
while (map_file >> type) {
|
||||
if (type == "pi") {
|
||||
int pi_idx;
|
||||
int woffset;
|
||||
std::string name;
|
||||
if (!(map_file >> pi_idx >> woffset >> name))
|
||||
log_error("Bad map file: couldn't read 'pi' line\n");
|
||||
int lit = (2 * pi_idx) + 2;
|
||||
if (lit < 0 || lit >= (int) bits.size())
|
||||
log_error("Bad map file: primary input literal out of range\n");
|
||||
Wire *w = module->wire(name);
|
||||
if (!w || woffset < 0 || woffset >= w->width)
|
||||
log_error("Map file references non-existent signal bit %s[%d]\n",
|
||||
name.c_str(), woffset);
|
||||
bits[lit] = SigBit(w, woffset);
|
||||
} else if (type == "box") {
|
||||
int box_seq;
|
||||
std::string name;
|
||||
if (!(map_file >> box_seq >> name))
|
||||
log_error("Bad map file: couldn't read 'box' line\n");
|
||||
if (box_seq < 0)
|
||||
log_error("Bad map file: box out of range\n");
|
||||
|
||||
Cell *box = module->cell(RTLIL::escape_id(name));
|
||||
if (!box)
|
||||
log_error("Map file references non-existent box %s\n",
|
||||
name.c_str());
|
||||
|
||||
Module *def = design->module(box->type);
|
||||
if (def && !box->parameters.empty()) {
|
||||
// TODO: This is potentially costly even if a cached derivation exists
|
||||
def = design->module(def->derive(design, box->parameters));
|
||||
log_assert(def);
|
||||
}
|
||||
|
||||
if (!def)
|
||||
log_error("Bad map file: no module found for box type '%s'\n", box->type.unescape());
|
||||
|
||||
if (box_seq >= (int) boxes.size()) {
|
||||
boxes.resize(box_seq + 1);
|
||||
retained_boxes.resize(box_seq + 1);
|
||||
}
|
||||
boxes[box_seq] = std::make_pair(box, def);
|
||||
} else {
|
||||
std::string scratch;
|
||||
std::getline(map_file, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int) A; i++) {
|
||||
while (f->get() & 0x80 && !f->eof());
|
||||
while (f->get() & 0x80 && !f->eof());
|
||||
}
|
||||
|
||||
if (f->get() != 'c')
|
||||
log_error("Missing 'c' ahead of extensions\n");
|
||||
if (f->peek() == '\n')
|
||||
f->get();
|
||||
auto extensions_start = f->tellg();
|
||||
|
||||
log_debug("reading 'h' (first pass)\n");
|
||||
for (int c = f->get(); c != EOF; c = f->get()) {
|
||||
if (c == 'h') {
|
||||
uint32_t len, ci_num, co_num, pi_num, po_num, no_boxes;
|
||||
len = read_be32(*f);
|
||||
read_be32(*f); // version
|
||||
ci_num = read_be32(*f);
|
||||
co_num = read_be32(*f);
|
||||
pi_num = read_be32(*f);
|
||||
po_num = read_be32(*f);
|
||||
no_boxes = read_be32(*f);
|
||||
|
||||
log_debug("len=%u ci_num=%u co_num=%u pi_num=%u po_nun=%u no_boxes=%u\n",
|
||||
len, ci_num, co_num, pi_num, po_num, no_boxes);
|
||||
|
||||
int ci_counter = 0;
|
||||
for (uint32_t i = 0; i < no_boxes; i++) {
|
||||
/* unused box_inputs = */ read_be32(*f);
|
||||
YS_MAYBE_UNUSED auto box_outputs = read_be32(*f);
|
||||
/* unused box_id = */ read_be32(*f);
|
||||
auto box_seq = read_be32(*f);
|
||||
|
||||
log_assert(box_seq < boxes.size());
|
||||
|
||||
auto [cell, def] = boxes[box_seq];
|
||||
log_assert(cell && def);
|
||||
retained_boxes[box_seq] = true;
|
||||
|
||||
int box_ci_idx = 0;
|
||||
for (auto port_id : def->ports) {
|
||||
Wire *port = def->wire(port_id);
|
||||
if (port->port_output) {
|
||||
if (!cell->hasPort(port_id) || cell->getPort(port_id).size() != port->width)
|
||||
log_error("Malformed design (1)\n");
|
||||
|
||||
SigSpec &conn = cell->connections_[port_id];
|
||||
for (int j = 0; j < port->width; j++) {
|
||||
if (conn[j].wire && conn[j].wire->port_output)
|
||||
conn[j] = module->addWire(module->uniquify(
|
||||
stringf("$box$%s$%s$%d",
|
||||
cell->name.isPublic() ? cell->name.c_str() + 1 : cell->name.c_str(),
|
||||
port_id.isPublic() ? port_id.c_str() + 1 : port_id.c_str(),
|
||||
j)));
|
||||
|
||||
bits[2*(pi_num + ci_counter + box_ci_idx++) + 2] = conn[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_assert(box_ci_idx == (int) box_outputs);
|
||||
ci_counter += box_ci_idx;
|
||||
}
|
||||
log_assert(pi_num + ci_counter == ci_num);
|
||||
} else if (c == '\n') {
|
||||
break;
|
||||
} else if (c == 'c') {
|
||||
break;
|
||||
} else {
|
||||
uint32_t len = read_be32(*f);
|
||||
f->ignore(len);
|
||||
log_debug(" section '%c' (%d): ignoring %d bytes\n", c, c, len);
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("reading 'M' (second pass)\n");
|
||||
|
||||
f->seekg(extensions_start);
|
||||
bool read_mapping = false;
|
||||
uint32_t no_cells, no_instances;
|
||||
for (int c = f->get(); c != EOF; c = f->get()) {
|
||||
if (c == 'M') {
|
||||
uint32_t len = read_be32(*f);
|
||||
read_mapping = true;
|
||||
|
||||
no_cells = read_be32(*f);
|
||||
no_instances = read_be32(*f);
|
||||
|
||||
log_debug("M: len=%u no_cells=%u no_instances=%u\n", len, no_cells, no_instances);
|
||||
|
||||
struct MappingCell {
|
||||
RTLIL::IdString type;
|
||||
RTLIL::IdString out;
|
||||
std::vector<RTLIL::IdString> ins;
|
||||
};
|
||||
std::vector<MappingCell> cells;
|
||||
cells.resize(no_cells);
|
||||
|
||||
for (unsigned i = 0; i < no_cells; ++i) {
|
||||
auto &cell = cells[i];
|
||||
cell.type = read_idstring(*f);
|
||||
cell.out = read_idstring(*f);
|
||||
uint32_t nins = read_be32(*f);
|
||||
for (uint32_t j = 0; j < nins; j++)
|
||||
cell.ins.push_back(read_idstring(*f));
|
||||
log_debug("M: Cell %s (out %s, ins", cell.type.unescape(), cell.out.unescape());
|
||||
for (auto in : cell.ins)
|
||||
log_debug(" %s", in.unescape());
|
||||
log_debug(")\n");
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < no_instances; ++i) {
|
||||
uint32_t cell_id = read_be32(*f);
|
||||
uint32_t out_lit = read_be32(*f);
|
||||
|
||||
log_assert(out_lit < bits.size());
|
||||
log_assert(bits[out_lit] == RTLIL::Sm);
|
||||
log_assert(cell_id < cells.size());
|
||||
auto &cell = cells[cell_id];
|
||||
Cell *instance = module->addCell(module->uniquify(stringf("$sc%d", out_lit)), cell.type);
|
||||
auto out_w = module->addWire(module->uniquify(stringf("$lit%d", out_lit)));
|
||||
instance->setPort(cell.out, out_w);
|
||||
bits[out_lit] = out_w;
|
||||
for (auto in : cell.ins) {
|
||||
uint32_t in_lit = read_be32(*f);
|
||||
log_assert(out_lit < bits.size());
|
||||
log_assert(bits[in_lit] != RTLIL::Sm);
|
||||
instance->setPort(in, bits[in_lit]);
|
||||
}
|
||||
}
|
||||
} else if (c == '\n') {
|
||||
break;
|
||||
} else if (c == 'c') {
|
||||
break;
|
||||
} else {
|
||||
uint32_t len = read_be32(*f);
|
||||
f->ignore(len);
|
||||
log_debug(" section '%c' (%d): ignoring %d bytes\n", c, c, len);
|
||||
}
|
||||
}
|
||||
|
||||
if (!read_mapping)
|
||||
log_error("Missing mapping (no 'M' section)\n");
|
||||
|
||||
log("Read %d instances with cell library of size %d.\n",
|
||||
no_instances, no_cells);
|
||||
|
||||
f->seekg(extensions_start);
|
||||
log_debug("reading 'h' (second pass)\n");
|
||||
int co_counter = 0;
|
||||
for (int c = f->get(); c != EOF; c = f->get()) {
|
||||
if (c == 'h') {
|
||||
uint32_t len, ci_num, co_num, pi_num, po_num, no_boxes;
|
||||
len = read_be32(*f);
|
||||
read_be32(*f);
|
||||
ci_num = read_be32(*f);
|
||||
co_num = read_be32(*f);
|
||||
pi_num = read_be32(*f);
|
||||
po_num = read_be32(*f);
|
||||
no_boxes = read_be32(*f);
|
||||
|
||||
log_debug("len=%u ci_num=%u co_num=%u pi_num=%u po_nun=%u no_boxes=%u\n",
|
||||
len, ci_num, co_num, pi_num, po_num, no_boxes);
|
||||
|
||||
for (uint32_t i = 0; i < no_boxes; i++) {
|
||||
YS_MAYBE_UNUSED auto box_inputs = read_be32(*f);
|
||||
/* unused box_outputs = */ read_be32(*f);
|
||||
/* unused box_id = */ read_be32(*f);
|
||||
auto box_seq = read_be32(*f);
|
||||
|
||||
log_assert(box_seq < boxes.size());
|
||||
|
||||
auto [cell, def] = boxes[box_seq];
|
||||
log_assert(cell && def);
|
||||
|
||||
int box_co_idx = 0;
|
||||
for (auto port_id : def->ports) {
|
||||
Wire *port = def->wire(port_id);
|
||||
SigSpec conn;
|
||||
if (port->port_input) {
|
||||
if (!cell->hasPort(port_id) || cell->getPort(port_id).size() != port->width)
|
||||
log_error("Malformed design (2)\n");
|
||||
|
||||
SigSpec conn;
|
||||
for (int j = 0; j < port->width; j++) {
|
||||
log_assert(co_counter + box_co_idx < (int) outputs.size());
|
||||
int lit = outputs[co_counter + box_co_idx++];
|
||||
log_assert(lit >= 0 && lit < (int) bits.size());
|
||||
SigBit bit = bits[lit];
|
||||
if (bit == RTLIL::Sm)
|
||||
log_error("Malformed mapping (1)\n");
|
||||
conn.append(bit);
|
||||
}
|
||||
cell->setPort(port_id, conn);
|
||||
}
|
||||
}
|
||||
|
||||
log_assert(box_co_idx == (int) box_inputs);
|
||||
co_counter += box_co_idx;
|
||||
}
|
||||
log_assert(po_num + co_counter == co_num);
|
||||
} else if (c == '\n') {
|
||||
break;
|
||||
} else if (c == 'c') {
|
||||
break;
|
||||
} else {
|
||||
uint32_t len = read_be32(*f);
|
||||
f->ignore(len);
|
||||
log_debug(" section '%c' (%d): ignoring %d bytes\n", c, c, len);
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
std::string scratch;
|
||||
std::getline(*f, scratch);
|
||||
if (f->eof())
|
||||
break;
|
||||
log_assert(!f->fail());
|
||||
log("input file: %s\n", scratch);
|
||||
}
|
||||
|
||||
log_debug("co_counter=%d\n", co_counter);
|
||||
|
||||
// TODO: seek without close/open
|
||||
map_file.close();
|
||||
map_file.open(map_filename);
|
||||
while (map_file >> type) {
|
||||
if (type == "po") {
|
||||
int po_idx;
|
||||
int woffset;
|
||||
std::string name;
|
||||
if (!(map_file >> po_idx >> woffset >> name))
|
||||
log_error("Bad map file: couldn't read 'po' line\n");
|
||||
po_idx += co_counter;
|
||||
if (po_idx < 0 || po_idx >= (int) outputs.size())
|
||||
log_error("Bad map file: primary output index out of range\n");
|
||||
int lit = outputs[po_idx];
|
||||
if (lit < 0 || lit >= (int) bits.size())
|
||||
log_error("Bad map file: primary output literal out of range\n");
|
||||
if (bits[lit] == RTLIL::Sm)
|
||||
log_error("Bad map file: primary output literal is a marker\n");
|
||||
Wire *w = module->wire(name);
|
||||
if (!w || woffset < 0 || woffset >= w->width)
|
||||
log_error("Map file references non-existent signal bit %s[%d]\n",
|
||||
name.c_str(), woffset);
|
||||
module->connect(SigBit(w, woffset), bits[lit]);
|
||||
} else if (type == "pseudopo") {
|
||||
int po_idx;
|
||||
int poffset;
|
||||
std::string box_name;
|
||||
std::string box_port;
|
||||
if (!(map_file >> po_idx >> poffset >> box_name >> box_port))
|
||||
log_error("Bad map file: couldn't read 'pseudopo' line\n");
|
||||
po_idx += co_counter;
|
||||
if (po_idx < 0 || po_idx >= (int) outputs.size())
|
||||
log_error("Bad map file: pseudo primary output index out of range\n");
|
||||
int lit = outputs[po_idx];
|
||||
if (lit < 0 || lit >= (int) bits.size())
|
||||
log_error("Bad map file: pseudo primary output literal out of range\n");
|
||||
if (bits[lit] == RTLIL::Sm)
|
||||
log_error("Bad map file: pseudo primary output literal is a marker\n");
|
||||
Cell *cell = module->cell(box_name);
|
||||
if (!cell || !cell->hasPort(box_port))
|
||||
log_error("Map file references non-existent box port %s/%s\n",
|
||||
box_name.c_str(), box_port.c_str());
|
||||
SigSpec &port = cell->connections_[box_port];
|
||||
if (poffset < 0 || poffset >= port.size())
|
||||
log_error("Map file references non-existent box port bit %s/%s[%d]\n",
|
||||
box_name.c_str(), box_port.c_str(), poffset);
|
||||
port[poffset] = bits[lit];
|
||||
} else {
|
||||
std::string scratch;
|
||||
std::getline(map_file, scratch);
|
||||
}
|
||||
}
|
||||
|
||||
int box_seq = 0;
|
||||
for (auto [cell, def] : boxes) {
|
||||
if (!retained_boxes[box_seq++])
|
||||
module->remove(cell);
|
||||
}
|
||||
}
|
||||
|
||||
void execute(std::istream *&f, std::string filename, std::vector<std::string> args, Design *design) override
|
||||
{
|
||||
log_header(design, "Executing XAIGER2 frontend.\n");
|
||||
|
||||
if (args.size() > 1 && args[1] == "-sc_mapping") {
|
||||
read_sc_mapping(f, filename, args, design);
|
||||
return;
|
||||
}
|
||||
|
||||
log_cmd_error("Mode '-sc_mapping' must be selected\n");
|
||||
}
|
||||
} Xaiger2Frontend;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
@@ -827,6 +827,7 @@ X(abc9_box_id)
|
||||
X(abc9_box_seq)
|
||||
X(abc9_bypass)
|
||||
X(abc9_carry)
|
||||
X(abc9_cell)
|
||||
X(abc9_deferred_box)
|
||||
X(abc9_flop)
|
||||
X(abc9_keep)
|
||||
|
||||
@@ -102,7 +102,6 @@ yosys_pass(abc_new
|
||||
abc9_exe
|
||||
abc9_ops
|
||||
box_derive
|
||||
read_xaiger2
|
||||
write_xaiger2
|
||||
)
|
||||
|
||||
|
||||
@@ -193,8 +193,9 @@ struct AbcNewPass : public ScriptPass {
|
||||
run(stringf(" abc9_ops -write_box %s/input.box", tmpdir));
|
||||
run(stringf(" write_xaiger2 -mapping_prep -map2 %s/input.map2 %s/input.xaig", tmpdir, tmpdir));
|
||||
run(stringf(" abc9_exe %s -cwd %s -box %s/input.box", exe_options, tmpdir, tmpdir));
|
||||
run(stringf(" read_xaiger2 -sc_mapping -module_name %s -map2 %s/input.map2 %s/output.aig",
|
||||
modname.c_str(), tmpdir.c_str(), tmpdir.c_str()));
|
||||
run(stringf(" read_aiger -xaiger -module_name %s$abc9 %s/output.aig",
|
||||
modname, tmpdir));
|
||||
run(stringf(" abc_ops_reintegrate -map %s/input.map2", tmpdir));
|
||||
if (!help_mode && mod->has_attribute(ID(abc9_script))) {
|
||||
if (script_save.empty())
|
||||
active_design->scratchpad_unset("abc9.script");
|
||||
|
||||
@@ -50,6 +50,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, std::string map_filename)
|
||||
int co_count = design->scratchpad_get_int("read_aiger.co_count", 0);
|
||||
|
||||
dict<RTLIL::IdString, std::pair<int,int>> wideports_cache;
|
||||
dict<RTLIL::IdString, std::pair<RTLIL::IdString, RTLIL::IdString>> pseudopos;
|
||||
|
||||
if (!map_filename.empty()) {
|
||||
std::ifstream mf(map_filename);
|
||||
@@ -150,6 +151,28 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, std::string map_filename)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == "pseudopo") {
|
||||
std::string port;
|
||||
mf >> port;
|
||||
RTLIL::IdString escaped_p = RTLIL::escape_id(port);
|
||||
|
||||
log_assert(variable + co_count < output_count);
|
||||
RTLIL::IdString wire_name = stringf("$aiger$o%d", variable + co_count);
|
||||
RTLIL::Wire* wire = mapped_mod->wire(wire_name);
|
||||
log_assert(wire);
|
||||
log_assert(wire->port_output);
|
||||
log_debug("Mapping pseudo output %s", wire);
|
||||
|
||||
if (index == 0) {
|
||||
pseudopos.insert({wire_name, std::make_pair(escaped_s, escaped_p)});
|
||||
log_debug(" -> %s.%s\n", escaped_s, escaped_p);
|
||||
}
|
||||
else {
|
||||
RTLIL::IdString indexed_name = stringf("%s[%d]", escaped_s, index);
|
||||
pseudopos.insert({wire_name, std::make_pair(indexed_name, escaped_p)});
|
||||
log_debug(" -> %s.%s\n", indexed_name, escaped_p);
|
||||
}
|
||||
}
|
||||
else if (type == "box") {
|
||||
RTLIL::Cell* cell = mapped_mod->cell(stringf("$box%d", variable));
|
||||
if (!cell)
|
||||
@@ -352,7 +375,7 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, std::string map_filename)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mapped_cell->type == ID($lut)) {
|
||||
if (mapped_cell->type == ID($lut) || mapped_cell->get_bool_attribute(ID::abc9_cell)) {
|
||||
RTLIL::Cell *cell = module->addCell(remap_name(mapped_cell->name), mapped_cell->type);
|
||||
cell->parameters = mapped_cell->parameters;
|
||||
cell->attributes = mapped_cell->attributes;
|
||||
@@ -506,6 +529,24 @@ void reintegrate(RTLIL::Module *module, bool dff_mode, std::string map_filename)
|
||||
log("ABC RESULTS: %15s cells: %8d\n", it.first, it.second);
|
||||
int in_wires = 0, out_wires = 0;
|
||||
|
||||
for (auto pseudopo : pseudopos) {
|
||||
auto wire_name = pseudopo.first;
|
||||
auto box_name = pseudopo.second.first;
|
||||
auto box_port_name = pseudopo.second.second;
|
||||
|
||||
RTLIL::Wire *mapped_wire = mapped_mod->wire(wire_name);
|
||||
log_assert(mapped_wire);
|
||||
auto box = module->cell(box_name);
|
||||
log_assert(box);
|
||||
|
||||
RTLIL::Wire *remap_wire = module->wire(remap_name(wire_name));
|
||||
box->setPort(box_port_name, remap_wire);
|
||||
|
||||
mapped_wire->port_output = false;
|
||||
}
|
||||
|
||||
mapped_mod->fixup_ports();
|
||||
|
||||
// Stitch in mapped_mod's inputs/outputs into module
|
||||
for (auto port : mapped_mod->ports) {
|
||||
RTLIL::Wire *mapped_wire = mapped_mod->wire(port);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
read_verilog <<EOT
|
||||
module sub(input a, b, c, output y);
|
||||
assign y = (a & b) | c;
|
||||
endmodule
|
||||
module top(input a, b, c, d, output y, z);
|
||||
assign z = (a ^ b) & d;
|
||||
sub s_i (.a(a), .b(b), .c(c), .y(y));
|
||||
endmodule
|
||||
EOT
|
||||
hierarchy -top top
|
||||
techmap
|
||||
abc_new -liberty ../liberty/normal.lib -liberty ../liberty/dff.lib
|
||||
|
||||
@@ -56,5 +56,5 @@ endmodule
|
||||
|
||||
EOF
|
||||
|
||||
logger -expect error "Malformed design" 1
|
||||
logger -expect error "Cannot find existing box cell" 1
|
||||
abc_new -liberty ../../tests/liberty/normal.lib -liberty ../../tests/liberty/dff.lib
|
||||
|
||||
Reference in New Issue
Block a user