pass metadata: initial commit of the metadata pass for exporting design metadata...
[yosys.git] / passes / equiv / equiv_simple.cc
index fa22dc62164f38d61e9872fc9aa25ca9b428abbc..7621341a7c30dd99b6046b415260743dc078d2f0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  yosys -- Yosys Open SYnthesis Suite
  *
- *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
  *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
@@ -35,13 +35,14 @@ struct EquivSimpleWorker
        ezSatPtr ez;
        SatGen satgen;
        int max_seq;
+       bool short_cones;
        bool verbose;
 
        pool<pair<Cell*, int>> imported_cells_cache;
 
-       EquivSimpleWorker(const vector<Cell*> &equiv_cells, SigMap &sigmap, dict<SigBit, Cell*> &bit2driver, int max_seq, bool verbose, bool model_undef) :
+       EquivSimpleWorker(const vector<Cell*> &equiv_cells, SigMap &sigmap, dict<SigBit, Cell*> &bit2driver, int max_seq, bool short_cones, bool verbose, bool model_undef) :
                        module(equiv_cells.front()->module), equiv_cells(equiv_cells), equiv_cell(nullptr),
-                       sigmap(sigmap), bit2driver(bit2driver), satgen(ez.get(), &sigmap), max_seq(max_seq), verbose(verbose)
+                       sigmap(sigmap), bit2driver(bit2driver), satgen(ez.get(), &sigmap), max_seq(max_seq), short_cones(short_cones), verbose(verbose)
        {
                satgen.model_undef = model_undef;
        }
@@ -59,8 +60,8 @@ struct EquivSimpleWorker
                for (auto &conn : cell->connections())
                        if (yosys_celltypes.cell_input(cell->type, conn.first))
                                for (auto bit : sigmap(conn.second)) {
-                                       if (cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_")) {
-                                               if (!conn.first.in("\\CLK", "\\C"))
+                                       if (cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_), ID($ff), ID($_FF_))) {
+                                               if (!conn.first.in(ID::CLK, ID::C))
                                                        next_seed.insert(bit);
                                        } else
                                                find_input_cone(next_seed, cells_cone, bits_cone, cells_stop, bits_stop, input_bits, bit);
@@ -89,8 +90,8 @@ struct EquivSimpleWorker
 
        bool run_cell()
        {
-               SigBit bit_a = sigmap(equiv_cell->getPort("\\A")).as_bit();
-               SigBit bit_b = sigmap(equiv_cell->getPort("\\B")).as_bit();
+               SigBit bit_a = sigmap(equiv_cell->getPort(ID::A)).as_bit();
+               SigBit bit_b = sigmap(equiv_cell->getPort(ID::B)).as_bit();
                int ez_context = ez->frozen_literal();
 
                if (satgen.model_undef)
@@ -114,9 +115,9 @@ struct EquivSimpleWorker
 
                if (verbose) {
                        log("  Trying to prove $equiv cell %s:\n", log_id(equiv_cell));
-                       log("    A = %s, B = %s, Y = %s\n", log_signal(bit_a), log_signal(bit_b), log_signal(equiv_cell->getPort("\\Y")));
+                       log("    A = %s, B = %s, Y = %s\n", log_signal(bit_a), log_signal(bit_b), log_signal(equiv_cell->getPort(ID::Y)));
                } else {
-                       log("  Trying to prove $equiv for %s:", log_signal(equiv_cell->getPort("\\Y")));
+                       log("  Trying to prove $equiv for %s:", log_signal(equiv_cell->getPort(ID::Y)));
                }
 
                int step = max_seq;
@@ -142,27 +143,53 @@ struct EquivSimpleWorker
                        pool<SigBit> short_bits_cone_a, short_bits_cone_b;
                        pool<SigBit> input_bits;
 
-                       for (auto bit_a : seed_a)
-                               find_input_cone(next_seed_a, short_cells_cone_a, short_bits_cone_a, full_cells_cone_b, full_bits_cone_b, &input_bits, bit_a);
-                       next_seed_a.swap(seed_a);
+                       if (short_cones)
+                       {
+                               for (auto bit_a : seed_a)
+                                       find_input_cone(next_seed_a, short_cells_cone_a, short_bits_cone_a, full_cells_cone_b, full_bits_cone_b, &input_bits, bit_a);
+                               next_seed_a.swap(seed_a);
 
-                       for (auto bit_b : seed_b)
-                               find_input_cone(next_seed_b, short_cells_cone_b, short_bits_cone_b, full_cells_cone_a, full_bits_cone_a, &input_bits, bit_b);
-                       next_seed_b.swap(seed_b);
+                               for (auto bit_b : seed_b)
+                                       find_input_cone(next_seed_b, short_cells_cone_b, short_bits_cone_b, full_cells_cone_a, full_bits_cone_a, &input_bits, bit_b);
+                               next_seed_b.swap(seed_b);
+                       }
+                       else
+                       {
+                               short_cells_cone_a = full_cells_cone_a;
+                               short_bits_cone_a = full_bits_cone_a;
+                               next_seed_a.swap(seed_a);
+
+                               short_cells_cone_b = full_cells_cone_b;
+                               short_bits_cone_b = full_bits_cone_b;
+                               next_seed_b.swap(seed_b);
+                       }
 
                        pool<Cell*> problem_cells;
                        problem_cells.insert(short_cells_cone_a.begin(), short_cells_cone_a.end());
                        problem_cells.insert(short_cells_cone_b.begin(), short_cells_cone_b.end());
 
                        if (verbose)
+                       {
                                log("    Adding %d new cells to the problem (%d A, %d B, %d shared).\n",
                                                GetSize(problem_cells), GetSize(short_cells_cone_a), GetSize(short_cells_cone_b),
                                                (GetSize(short_cells_cone_a) + GetSize(short_cells_cone_b)) - GetSize(problem_cells));
+                       #if 0
+                               for (auto cell : short_cells_cone_a)
+                                       log("      A-side cell: %s\n", log_id(cell));
+
+                               for (auto cell : short_cells_cone_b)
+                                       log("      B-side cell: %s\n", log_id(cell));
+                       #endif
+                       }
 
                        for (auto cell : problem_cells) {
                                auto key = pair<Cell*, int>(cell, step+1);
-                               if (!imported_cells_cache.count(key) && !satgen.importCell(cell, step+1))
-                                       log_cmd_error("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type));
+                               if (!imported_cells_cache.count(key) && !satgen.importCell(cell, step+1)) {
+                                       if (RTLIL::builtin_ff_cell_types().count(cell->type))
+                                               log_cmd_error("No SAT model available for async FF cell %s (%s).  Consider running `async2sync` or `clk2fflogic` first.\n", log_id(cell), log_id(cell->type));
+                                       else
+                                               log_cmd_error("No SAT model available for cell %s (%s).\n", log_id(cell), log_id(cell->type));
+                               }
                                imported_cells_cache.insert(key);
                        }
 
@@ -176,7 +203,7 @@ struct EquivSimpleWorker
 
                        if (!ez->solve(ez_context)) {
                                log(verbose ? "    Proved equivalence! Marking $equiv cell as proven.\n" : " success!\n");
-                               equiv_cell->setPort("\\B", equiv_cell->getPort("\\A"));
+                               equiv_cell->setPort(ID::B, equiv_cell->getPort(ID::A));
                                ez->assume(ez->NOT(ez_context));
                                return true;
                        }
@@ -233,7 +260,7 @@ struct EquivSimpleWorker
                if (GetSize(equiv_cells) > 1) {
                        SigSpec sig;
                        for (auto c : equiv_cells)
-                               sig.append(sigmap(c->getPort("\\Y")));
+                               sig.append(sigmap(c->getPort(ID::Y)));
                        log(" Grouping SAT models for %s:\n", log_signal(sig));
                }
 
@@ -250,7 +277,7 @@ struct EquivSimpleWorker
 
 struct EquivSimplePass : public Pass {
        EquivSimplePass() : Pass("equiv_simple", "try proving simple $equiv instances") { }
-       virtual void help()
+       void help() override
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
@@ -264,6 +291,10 @@ struct EquivSimplePass : public Pass {
                log("    -undef\n");
                log("        enable modelling of undef states\n");
                log("\n");
+               log("    -short\n");
+               log("        create shorter input cones that stop at shared nodes. This yields\n");
+               log("        simpler SAT problems but sometimes fails to prove equivalence.\n");
+               log("\n");
                log("    -nogroup\n");
                log("        disabling grouping of $equiv cells by output wire\n");
                log("\n");
@@ -271,13 +302,13 @@ struct EquivSimplePass : public Pass {
                log("        the max. number of time steps to be considered (default = 1)\n");
                log("\n");
        }
-       virtual void execute(std::vector<std::string> args, Design *design)
+       void execute(std::vector<std::string> args, Design *design) override
        {
-               bool verbose = false, model_undef = false, nogroup = false;
+               bool verbose = false, short_cones = false, model_undef = false, nogroup = false;
                int success_counter = 0;
                int max_seq = 1;
 
-               log_header("Executing EQUIV_SIMPLE pass.\n");
+               log_header(design, "Executing EQUIV_SIMPLE pass.\n");
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++) {
@@ -285,6 +316,10 @@ struct EquivSimplePass : public Pass {
                                verbose = true;
                                continue;
                        }
+                       if (args[argidx] == "-short") {
+                               short_cones = true;
+                               continue;
+                       }
                        if (args[argidx] == "-undef") {
                                model_undef = true;
                                continue;
@@ -313,8 +348,8 @@ struct EquivSimplePass : public Pass {
                        int unproven_cells_counter = 0;
 
                        for (auto cell : module->selected_cells())
-                               if (cell->type == "$equiv" && cell->getPort("\\A") != cell->getPort("\\B")) {
-                                       auto bit = sigmap(cell->getPort("\\Y").as_bit());
+                               if (cell->type == ID($equiv) && cell->getPort(ID::A) != cell->getPort(ID::B)) {
+                                       auto bit = sigmap(cell->getPort(ID::Y).as_bit());
                                        auto bit_group = bit;
                                        if (!nogroup && bit_group.wire)
                                                bit_group.offset = 0;
@@ -329,7 +364,7 @@ struct EquivSimplePass : public Pass {
                                        unproven_cells_counter, GetSize(unproven_equiv_cells), log_id(module));
 
                        for (auto cell : module->cells()) {
-                               if (!ct.cell_known(cell->type) && !cell->type.in("$dff", "$_DFF_P_", "$_DFF_N_"))
+                               if (!ct.cell_known(cell->type) && !cell->type.in(ID($dff), ID($_DFF_P_), ID($_DFF_N_), ID($ff), ID($_FF_)))
                                        continue;
                                for (auto &conn : cell->connections())
                                        if (yosys_celltypes.cell_output(cell->type, conn.first))
@@ -346,7 +381,7 @@ struct EquivSimplePass : public Pass {
                                for (auto it2 : it.second)
                                        cells.push_back(it2.second);
 
-                               EquivSimpleWorker worker(cells, sigmap, bit2driver, max_seq, verbose, model_undef);
+                               EquivSimpleWorker worker(cells, sigmap, bit2driver, max_seq, short_cones, verbose, model_undef);
                                success_counter += worker.run();
                        }
                }