From 4c0a8a132614ee354913815f3b651f8735a3a730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Povi=C5=A1er?= Date: Sat, 5 Oct 2024 18:04:45 +0200 Subject: [PATCH] aiger2: Add analysis step to order boxes --- backends/aiger2/aiger.cc | 122 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/backends/aiger2/aiger.cc b/backends/aiger2/aiger.cc index 9df9c9b20..b6994c221 100644 --- a/backends/aiger2/aiger.cc +++ b/backends/aiger2/aiger.cc @@ -537,6 +537,11 @@ struct Index { } }; + bool visit_hook(int idx, HierCursor &cursor, SigBit bit) + { + return false; + } + Lit visit(HierCursor &cursor, SigBit bit) { if (!bit.wire) { @@ -554,6 +559,12 @@ struct Index { return lits[idx]; } + // provide means for the derived class to override + // the visit behavior + if ((static_cast(this))->visit_hook(idx, cursor, bit)) { + return lits[idx]; + } + Lit ret; if (!bit.wire->port_input) { // an output of a cell @@ -791,6 +802,102 @@ struct AigerWriter : Index { } }; +struct XAigerAnalysis : Index { + const static int CONST_FALSE = 0; + const static int CONST_TRUE = 0; + const static constexpr int EMPTY_LIT = -1; + + XAigerAnalysis() + { + allow_blackboxes = true; + + // Disable const folding and strashing as literal values are not unique + const_folding = false; + strashing = false; + } + + static int negate(int lit) + { + return lit; + } + + int emit_gate(int a, int b) + { + return max(a, b) + 1; + } + + pool seen; + + bool visit_hook(int idx, HierCursor &cursor, SigBit bit) + { + log_assert(cursor.is_top()); // TOOD: fix analyzer to work with hierarchy + + if (bit.wire->port_input) + return false; + + Cell *driver = bit.wire->driverCell(); + if (!driver->type.isPublic()) + return false; + + Module *mod = design->module(driver->type); + log_assert(mod); + if (!mod->has_attribute(ID::abc9_box_id)) + return false; + + int max = 1; + for (auto wire : mod->wires()) + if (wire->port_input) + for (int i = 0; i < wire->width; i++) { + int ilevel = visit(cursor, driver->getPort(wire->name)[i]); + max = std::max(max, ilevel + 1); + } + lits[idx] = max; + + if (!seen.count(driver)) + seen.insert(driver); + + return true; + } + + void analyze(Module *top) + { + setup(top); + + for (auto id : top->ports) { + Wire *w = top->wire(id); + log_assert(w); + if (w->port_input) + for (int i = 0; i < w->width; i++) + pi_literal(SigBit(w, i)) = 0; + } + + HierCursor cursor; + for (auto box : top_minfo->found_blackboxes) { + Module *def = design->module(box->type); + if (!box->type.isPublic() || (def && !def->has_attribute(ID::abc9_box_id))) + for (auto &conn : box->connections_) + if (box->output(conn.first)) + for (auto bit : conn.second) + pi_literal(bit, &cursor) = 0; + } + + for (auto w : top->wires()) + if (w->port_output) { + for (auto bit : SigSpec(w)) + (void) eval_po(bit); + } + + for (auto box : top_minfo->found_blackboxes) { + Module *def = design->module(box->type); + if (!box->type.isPublic() || (def && !def->has_attribute(ID::abc9_box_id))) + for (auto &conn : box->connections_) + if (box->input(conn.first)) + for (auto bit : conn.second) + (void) eval_po(bit); + } + } +}; + struct XAigerWriter : AigerWriter { XAigerWriter() { @@ -897,6 +1004,11 @@ struct XAigerWriter : AigerWriter { void prep_boxes(int pending_pos_num) { + XAigerAnalysis analysis; + log_debug("preforming analysis on '%s'\n", log_id(top)); + analysis.analyze(top); + log_debug("analysis on '%s' done\n", log_id(top)); + // boxes which have timing data, maybe a whitebox model std::vector> nonopaque_boxes; // boxes which are fully opaque @@ -942,6 +1054,16 @@ struct XAigerWriter : AigerWriter { int box_seq = 0; + std::vector boxes_order(analysis.seen.begin(), analysis.seen.end()); + std::reverse(boxes_order.begin(), boxes_order.end()); + + nonopaque_boxes.clear(); + for (auto box : boxes_order) { + HierCursor cursor; + Module *def = design->module(box->type); + nonopaque_boxes.push_back(std::make_tuple(cursor, box, def)); + } + for (auto [cursor, box, def] : nonopaque_boxes) { // use `def->name` not `box->type` as we want the derived type Cell *holes_wb = holes_module->addCell(NEW_ID, def->name);