Code Monkey home page Code Monkey logo

mockturtle's People

Contributors

aletempiac avatar b1f6c1c4 avatar bugraeryilmaz avatar costamag avatar drewniok avatar eletesta avatar gmeuli avatar guilhemn avatar hriener avatar jblanusa avatar lee30sonia avatar lrkkr avatar marcelwa avatar maustin8 avatar mdsudara avatar msoeken avatar nozidoali avatar rocallahan avatar sahandkashani avatar shubhamrai26 avatar whaaswijk avatar wlneto avatar zfchu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mockturtle's Issues

seg fault on lut_mapping

Dears,
I've found a possible issue when lut_mapping is used.
I've slightly changed the experiment file experiments/lut_mapping.cpp in this way:

/* mockturtle: C++ logic network library
 * Copyright (C) 2018-2019  EPFL
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <string>
#include <vector>

#include <fmt/format.h>
#include <lorina/aiger.hpp>
#include <mockturtle/algorithms/collapse_mapped.hpp>
#include <mockturtle/algorithms/equivalence_checking.hpp>
#include <mockturtle/algorithms/lut_mapping.hpp>
#include <mockturtle/algorithms/miter.hpp>
#include <mockturtle/io/bench_reader.hpp>
#include <mockturtle/networks/aig.hpp>
#include <mockturtle/networks/klut.hpp>
#include <mockturtle/views/mapping_view.hpp>

#include <experiments.hpp>
#include <mockturtle/mockturtle.hpp>

int main()
{
  using namespace experiments;
  using namespace mockturtle;

  experiment<std::string, uint32_t, double, double, bool> exp( "lut_mapping", "benchmark", "luts", "runtime", "runtime cec", "equivalent" );

  for ( auto const& benchmark : epfl_benchmarks( ( adder | bar | max | experiments::random ) & ~mem_ctrl & ~voter ) )
  {
    fmt::print( "[i] processing {}\n", benchmark );
    klut_network aig;
    lorina::read_bench( "file.bench", bench_reader( aig ) );

    lut_mapping_stats st;
    mapping_view<klut_network, true> mapped_aig{aig};
    lut_mapping<decltype( mapped_aig ), true>( mapped_aig, {}, &st );
    const auto klut = *collapse_mapped_network<klut_network>( mapped_aig );

    equivalence_checking_stats ecst;
    auto cec = *equivalence_checking( *miter<klut_network>( aig, klut ), {}, &ecst );

    exp( benchmark, klut.num_gates(), to_seconds( st.time_total ), to_seconds( ecst.time_total ), cec );
  }

  exp.save();
  exp.table();

  return 0;
}


```if file.bench is defined in this way:
INPUT(n2)
OUTPUT(po0)
n0 = gnd
n1 = vdd
n3 = LUT 0x6 (n2, n1)
po0 = LUT 0x2 (n3)
you are going to have the seg fault

kind regards,
Fabrizio

Segfault when combining with lut

Hi,

I am checking the options of using mockturtle in lgraph (https://github.com/masc-ucsc/lgraph), but I have this seg-fault when I combine optimizations with lut mapping.

The following programs works fine, but if I define BUG1 or BUG2, it has a seg-fault. Looks like the cut_enumeration fails.

#include <iostream>
#include <sstream>

#include <mockturtle/algorithms/cut_enumeration.hpp>

#include <mockturtle/algorithms/resubstitution.hpp>

#include <mockturtle/algorithms/refactoring.hpp>

#include <mockturtle/algorithms/collapse_mapped.hpp>

#include <mockturtle/algorithms/node_resynthesis.hpp>
#include <mockturtle/algorithms/node_resynthesis/akers.hpp>
#include <mockturtle/algorithms/node_resynthesis/direct.hpp>
#include <mockturtle/algorithms/node_resynthesis/mig_npn.hpp>
#include <mockturtle/algorithms/node_resynthesis/xmg_npn.hpp>

#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/generators/arithmetic.hpp>
#include <mockturtle/io/write_bench.hpp>
#include <mockturtle/networks/aig.hpp>
#include <mockturtle/networks/klut.hpp>
#include <mockturtle/networks/mig.hpp>

#include <mockturtle/algorithms/lut_mapping.hpp>
#include <mockturtle/views/mapping_view.hpp>

using namespace mockturtle;

//#define BUG1
//#define BUG2

int main() {

  mig_network aig;

  mig_network::signal array[32];
  mig_network::signal array2[32];

  for(int i=0;i<32;i++) {
    array[i] = aig.create_pi();
  }

  array2[0] = aig.create_xor(array[0],array[1]);
  for(int i=1;i<32;i++) {
    array2[i] = aig.create_xor(array[i],array2[i-1]);
  }

  aig.create_po( array2[31] );

#ifdef BUG1
  resubstitution(aig);
  cleanup_dangling(aig);
#endif

#ifdef BUG2
  //mig_npn_resynthesis resyn;
  akers_resynthesis<mig_network> resyn;
  refactoring(aig, resyn);
  //const auto mig = node_resynthesis<mig_network>( aig, resyn );
#endif

  mapping_view<mig_network, true> mapped_mig{aig};

  lut_mapping_params ps;
  ps.cut_enumeration_ps.cut_size = 6;
  lut_mapping<mapping_view<mig_network, true>, true>( mapped_mig, ps);
  auto lut =*collapse_mapped_network<klut_network>(mapped_mig);

  write_bench(lut, std::cout);
}

// g++ -std=c++17 -I ../../lib/sparsepp/ -I ../../lib/fmt/ -I ../../lib/ez/ -I ../../lib/kitty/ -I ../../include/ test1.cpp ../../lib/fmt/fmt/*.cc

Balancing (and probably other optimizations) don't preserve names

We've run into an issue where, when optimizing a names_view, the names are not preserved through optimization. We've confirmed this is the case for balancing; it is likely true for other methods as well.
For example


creates a new network (which may be a names_view), the rest of the function then populates the network but the names from the original network are never copied over.

remove internal debug information for better benchmark?

Hi msoeken,
we are currently integrating mockturtle with lgraph
https://github.com/masc-ucsc/lgraph
and running some benchmarks for a woset19 paper

the basic flow is lgraph->mig->klut->lgraph
we notice that there are some internal debug information printed out like this,
it would be good to ifdef out these debug messages, can you help on this?
thanks

INPUT(n1)
INPUT(n2)
INPUT(n6)
INPUT(n10)
INPUT(n14)
INPUT(n18)
INPUT(n22)
INPUT(n26)
INPUT(n30)
INPUT(n34)
INPUT(n38)
OUTPUT(po0)
OUTPUT(po1)
OUTPUT(po2)
OUTPUT(po3)
OUTPUT(po4)
OUTPUT(po5)
OUTPUT(po6)
OUTPUT(po7)
OUTPUT(po8)
OUTPUT(po9)
n0 = gnd
n3 = LUT 0x8e (n0, n1, n2)
n4 = LUT 0xb2 (n0, n1, n2)
n5 = LUT 0xd4 (n0, n3, n4)
n7 = LUT 0x8e (n0, n5, n6)
n8 = LUT 0xb2 (n0, n5, n6)
n9 = LUT 0xd4 (n0, n7, n8)
n11 = LUT 0x8e (n0, n9, n10)
n12 = LUT 0xb2 (n0, n9, n10)
n13 = LUT 0xd4 (n0, n11, n12)
n15 = LUT 0x8e (n0, n13, n14)
n16 = LUT 0xb2 (n0, n13, n14)
n17 = LUT 0xd4 (n0, n15, n16)
n19 = LUT 0x8e (n0, n17, n18)
n20 = LUT 0xb2 (n0, n17, n18)
n21 = LUT 0xd4 (n0, n19, n20)
n23 = LUT 0x8e (n0, n21, n22)
n24 = LUT 0xb2 (n0, n21, n22)
n25 = LUT 0xd4 (n0, n23, n24)
n27 = LUT 0x8e (n0, n25, n26)
po6 = LUT 0x2 (n29)
po7 = LUT 0x2 (n33)
po8 = LUT 0x2 (n37)
po9 = LUT 0x2 (n41)
INPUT(n2)
INPUT(n3)
INPUT(n4)
INPUT(n5)
INPUT(n6)
INPUT(n7)
INPUT(n8)
INPUT(n9)
INPUT(n10)
INPUT(n11)
INPUT(n12)
OUTPUT(po0)
OUTPUT(po1)
OUTPUT(po2)
OUTPUT(po3)
OUTPUT(po4)
OUTPUT(po5)
OUTPUT(po6)
OUTPUT(po7)
OUTPUT(po8)
OUTPUT(po9)
n0 = gnd
n1 = vdd
n13 = LUT 0x6 (n2, n3)
n14 = LUT 0x96 (n2, n3, n4)
n15 = LUT 0x6996 (n2, n3, n4, n5)
n16 = LUT 0x6 (n6, n15)
n17 = LUT 0x96 (n6, n7, n15)
n18 = LUT 0x6996 (n6, n7, n8, n15)
n19 = LUT 0x6 (n9, n18)
n20 = LUT 0x96 (n9, n10, n18)
n21 = LUT 0x6996 (n9, n10, n11, n18)
n22 = LUT 0x6 (n12, n21)
po0 = LUT 0x2 (n13)
po1 = LUT 0x2 (n14)
po2 = LUT 0x2 (n15)
po3 = LUT 0x2 (n16)
po4 = LUT 0x2 (n17)
po5 = LUT 0x2 (n18)
po6 = LUT 0x2 (n19)
po7 = LUT 0x2 (n20)
po8 = LUT 0x2 (n21)
po9 = LUT 0x2 (n22)

Is it necessary to call the cleanup_dangling function after calling the mig_algebraic_depth_rewriting operation?

Hi,

I am implementing an algorithm that chains together a few operations for MIG graphs, and have noticed that after calling the mig_algebraic_depth_rewriting operation on a depth view of a MIG graph, I am not able to call the cut_rewriting operation on the original MIG graph (cut_rewriting uses the dsd_resynthesis resynthesis engine that uses direct_resynthesis as a fallback). In order to attempt to remedy this, I have tried calling the cleanup_dangling function on the original MIG graph, before calling the cut_rewriting function. This has solved my issue.

Now, after calling mig_algebraic_depth_rewriting, when examining the size and depth of the original MIG graph, before and after calling the cleanup_dangling function, I have observed that the size decreases while the depth remains the same. My question is: is this expected? I am asking because the Mockturtle documentation only specifies that the cleanup_dangling function should be called after the refactoring operation, and the documentation for Algebraic Rewriting does not mention that cleanup_dangling should be called after the operation at all.

Also, if this is the case and the cleanup_dangling should be called after mig_algebraic_depth_rewriting, I would like to also ask if it should also be called after any other operation applicable to MIGs except for refactoring? The operations that I am interested in in particular are: Cut rewriting, MIG algebraic rewriting, Resubstitution and Balancing.

Thanks a lot!

Refactoring creates cyclic network

Suspected bug in refactoring and/or direct_resynthesis reported by @KamilDre in #511.
Test case and code to reproduce:

module top( x0 , x1 , x2 , y0 );
  input x0 , x1 , x2 ;
  output y0 ;
  wire n4 , n5 , n6 , n7 , n8 , n9 , n10 , n11 , n12 , n13 , n14 , n15 , n16 , n17 , n18 , n19 , n20 , n21 , n22 , n23 , n24 , n25 , n26 , n27 ;
  assign n4 = x0 | x1 ;
  assign n5 = x1 & ~n4 ;
  assign n6 = x1 & ~x2 ;
  assign n7 = n5 & ~n6 ;
  assign n8 = x1 | n4 ;
  assign n9 = n6 | n8 ;
  assign n10 = ~n7 & n9 ;
  assign n11 = x0 & x1 ;
  assign n12 = ~n5 & n6 ;
  assign n13 = ~n11 & n12 ;
  assign n14 = n10 & ~n13 ;
  assign n15 = x0 & ~n4 ;
  assign n16 = x0 | n15 ;
  assign n17 = x0 & n15 ;
  assign n18 = n16 & ~n17 ;
  assign n19 = n14 & ~n18 ;
  assign n20 = n18 | n19 ;
  assign n21 = ( ~n14 & n19 ) | ( ~n14 & n20 ) | ( n19 & n20 ) ;
  assign n22 = ~n13 & n18 ;
  assign n23 = n10 & ~n22 ;
  assign n24 = n17 & ~n23 ;
  assign n25 = ~n17 & n23 ;
  assign n26 = n24 | n25 ;
  assign n27 = n21 | n26 ;
  assign y0 = ~n27 ;
endmodule
#include <mockturtle/networks/mig.hpp>
#include <mockturtle/io/verilog_reader.hpp>
#include <mockturtle/algorithms/refactoring.hpp>
#include <mockturtle/algorithms/node_resynthesis/direct.hpp>
#include <mockturtle/utils/debugging_utils.hpp>
#include <lorina/verilog.hpp>

int main()
{
    using namespace mockturtle;

    mig_network ntk;
    auto lorina_res = lorina::read_verilog( "acyclic.v", verilog_reader( ntk ) );
    assert( lorina_res == lorina::return_code::success );
    assert( network_is_acylic( ntk ) );

    direct_resynthesis<mig_network> resyn;
    refactoring( ntk, resyn );
    if ( network_is_acylic( ntk ) )
        return 0; // bug-free
    else
        return 1; // buggy
}

Note: The reproducibility of the bug using the above case might be platform-dependent, as the bug seems to be related to an uninitialized variable (see below).

simplify the mapped network by removing inv nodes

Dears,

Looking at the results of this simple code:

   lut_mapping_stats st;
   mapping_view<klut_network, true> mapped_aig{aig};
   lut_mapping<decltype( mapped_aig ), true>( mapped_aig, {}, &st );
   const auto klut = *collapse_mapped_network<klut_network>( mapped_aig );
   mockturtle::write_bench(klut, std::cout);

I've noticed a possible simple optimization to add to the mockturtle stack.
This is the resulting bench:

INPUT(n2)
INPUT(n3)
INPUT(n4)
INPUT(n5)
INPUT(n6)
INPUT(n7)
INPUT(n8)
INPUT(n9)
INPUT(n10)
INPUT(n11)
INPUT(n12)
INPUT(n13)
INPUT(n14)
INPUT(n15)
INPUT(n16)
INPUT(n17)
INPUT(n18)
INPUT(n19)
INPUT(n20)
INPUT(n21)
INPUT(n22)
INPUT(n23)
INPUT(n24)
INPUT(n25)
INPUT(n26)
INPUT(n27)
INPUT(n28)
INPUT(n29)
INPUT(n30)
INPUT(n31)
INPUT(n32)
INPUT(n33)
INPUT(n34)
INPUT(n35)
INPUT(n36)
INPUT(n37)
OUTPUT(po0)
OUTPUT(po1)
OUTPUT(po2)
OUTPUT(po3)
OUTPUT(po4)
OUTPUT(po5)
OUTPUT(po6)
OUTPUT(po7)
OUTPUT(po8)
OUTPUT(po9)
OUTPUT(po10)
OUTPUT(po11)
OUTPUT(po12)
OUTPUT(po13)
OUTPUT(po14)
OUTPUT(po15)
OUTPUT(po16)
OUTPUT(po17)
OUTPUT(po18)
OUTPUT(po19)
OUTPUT(po20)
OUTPUT(po21)
OUTPUT(po22)
OUTPUT(po23)
OUTPUT(po24)
OUTPUT(po25)
OUTPUT(po26)
OUTPUT(po27)
OUTPUT(po28)
OUTPUT(po29)
OUTPUT(po30)
OUTPUT(po31)
OUTPUT(po32)
OUTPUT(po33)
OUTPUT(po34)
OUTPUT(po35)
OUTPUT(po36)
OUTPUT(po37)
n0 = gnd
n1 = vdd
n38 = LUT 0x9 (n2, n3)
n39 = LUT 0x1 (n4)
n40 = LUT 0x1 (n5)
n41 = LUT 0x1 (n6)
n42 = LUT 0x1 (n7)
n43 = LUT 0x1 (n8)
n44 = LUT 0x1 (n2)
n45 = LUT 0x1 (n9)
n46 = LUT 0x0010 (n10, n11, n12, n15)
n47 = LUT 0x00040000 (n10, n11, n16, n17, n18)
n48 = LUT 0x4000 (n10, n11, n16, n19)
n49 = LUT 0x0040 (n10, n11, n16, n19)
n50 = LUT 0x02 (n10, n20, n21)
n51 = LUT 0x80 (n10, n20, n23)
n52 = LUT 0x10 (n10, n11, n12)
n53 = LUT 0x1 (n15)
n54 = LUT 0x0fff0888 (n10, n20, n52, n53, n49)
n55 = LUT 0x10 (n24, n25, n26)
n56 = LUT 0x0400 (n24, n25, n28, n29)
n57 = LUT 0x00040000 (n24, n25, n28, n29, n30)
n58 = LUT 0x02 (n24, n32, n33)
n59 = LUT 0x2000 (n24, n32, n33, n34)
n60 = LUT 0x08 (n24, n32, n35)
n61 = LUT 0x0302 (n12, n24, n25, n26)
n62 = LUT 0x1 (n24)
n63 = LUT 0xff80 (n25, n28, n62, n61)
n64 = LUT 0xbfffbfff1555bfff (n24, n25, n28, n31, n32, n35)
n65 = LUT 0x1 (n35)
n66 = LUT 0xbfff (n24, n25, n28, n31)
n67 = LUT 0x03020100ffffffff (n12, n24, n25, n26, n27, n66)
n68 = LUT 0x007f7f7f (n24, n32, n65, n63, n67)
n69 = LUT 0x0004 (n10, n11, n16, n36)
n70 = LUT 0x00001000 (n10, n11, n12, n15, n36)
n71 = LUT 0xf080 (n24, n32, n36, n63)
n72 = LUT 0xff20 (n25, n28, n62, n59)
n73 = LUT 0x8 (n36, n72)
n74 = LUT 0xf8 (n24, n32, n63)
n75 = LUT 0x000000000000fddd (n24, n32, n33, n34, n74, n72)
n76 = LUT 0x8 (n36, n75)
n77 = LUT 0x02 (n10, n20, n36)
n78 = LUT 0x0000000004040400 (n10, n11, n16, n17, n18, n36)
n79 = LUT 0x1 (n37)
n80 = LUT 0x1 (n36)
n81 = LUT 0xffffffff01000000 (n10, n11, n12, n13, n80, n77)
n82 = LUT 0x1 (n32)
n83 = LUT 0xff00ff002a000000 (n24, n33, n34, n36, n82, n72)
n84 = LUT 0xe (n76, n83)
n85 = LUT 0x00000222 (n10, n20, n21, n22, n36)
n86 = LUT 0x0000000000010000 (n10, n11, n12, n13, n14, n36)
n87 = LUT 0xfe (n69, n81, n86)
n88 = LUT 0x9 (n2, n81)
po0 = LUT 0x2 (n38)
po1 = LUT 0x2 (n39)
po2 = LUT 0x2 (n40)
po3 = LUT 0x2 (n41)
po4 = LUT 0x2 (n42)
po5 = LUT 0x2 (n43)
po6 = LUT 0x2 (n44)
po7 = LUT 0x2 (n45)
po8 = LUT 0x2 (n46)
po9 = LUT 0x2 (n47)
po10 = LUT 0x2 (n48)
po11 = LUT 0x2 (n49)
po12 = LUT 0x2 (n50)
po13 = LUT 0x2 (n51)
po14 = LUT 0x2 (n54)
po15 = LUT 0x2 (n55)
po16 = LUT 0x2 (n56)
po17 = LUT 0x2 (n57)
po18 = LUT 0x2 (n58)
po19 = LUT 0x2 (n59)
po20 = LUT 0x2 (n60)
po21 = LUT 0x2 (n61)
po22 = LUT 0x2 (n63)
po23 = LUT 0x2 (n64)
po24 = LUT 0x2 (n68)
po25 = LUT 0x2 (n69)
po26 = LUT 0x2 (n70)
po27 = LUT 0x2 (n71)
po28 = LUT 0x2 (n73)
po29 = LUT 0x2 (n76)
po30 = LUT 0x2 (n77)
po31 = LUT 0x2 (n78)
po32 = LUT 0x2 (n79)
po33 = LUT 0x2 (n81)
po34 = LUT 0x2 (n84)
po35 = LUT 0x2 (n85)
po36 = LUT 0x2 (n87)
po37 = LUT 0x2 (n88)

In particular, nodes like n53 could be subsumed in their fanout nodes such as n54. This reduces the number of LUTs and levels of the network without paying too much in code optimization complexity. Not sure if the best place to insert this is before collapse_mapped_network starts or after.

Cheers,
Fabrizio

missing namespace in example

The README gives the following example:

#include <mockturtle/mockturtle.hpp>
#include <lorina/aiger.hpp>

aig_network aig;
lorina::read_aiger( "file.aig", mockturtle::aiger_reader( aig ) );

const auto cuts = cut_enumeration( aig );
aig.foreach_node( [&]( auto node ) {
  std::cout << cuts.cuts( aig.node_to_index( node ) ) << "\n";
} );

When trying to run this, I found I needed to give the namespace for aig_network. I.e.

-aig_network aig;
+mockturtle::aig_network aig;

compile warnings: -Werror=unused-but-set-variable

Hi
I found some possible issues in the code.

In Solver::addClause_ variable flag is set but not used. Is this intended?

Lit p; int i, j, flag = 0;

In Solver::simplifyLearnt variables beforeSize and afterSize are set but not used. There were used when the printf was active.

int beforeSize, afterSize;

All these warnings come when option -Werror=unused-but-set-variable is passed to gcc compiler.
Cheers,
Fabrizio

Quality test are not passing.

There is an error in the [quality] tests which is not only about quality differences (regressions).
(Seems to be a problem with partial truth tables.)

Assertion failed: (first.num_vars() == second.num_vars()), function binary_operation, file /mockturtle/lib/kitty/kitty/algorithm.hpp, line 101.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
run_tests is a Catch v2.5.0 host application.
Run with -? for options

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Test quality improvement of MIG k-resubstitution
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/mockturtle/test/algorithms/quality.cpp:202
...........................................................................................................................................................................................................................................................................................................

/mockturtle/test/algorithms/quality.cpp:202: FAILED:
due to a fatal error condition:
  SIGABRT - Abort (abnormal termination) signal

===========================================================================================================================================================================================================================================================================================================
test cases:  173 |  172 passed | 1 failed
assertions: 6107 | 6106 passed | 1 failed

fish: Job 1, './test/run_tests' terminated by signal SIGABRT (Abort)

Is it intended that `create_pi()` does not trigger `on_add` events?

Describe the bug
First of all, I'm not sure whether this is a bug or intended behavior.

I have noticed that the default network implementations do not trigger the on_add events when their create_pi() function is called.

I found this behavior misleading as, e.g., depth_view makes explicit usage of this event type to recompute levels on creation of new nodes. There is a test case in depth_view.cpp that tests this feature which of course works because PIs are placed in level 0 anyway, i.e., the default-constructed value for the level data type (uint32_t). To be more precise, PIs show their intended level on creation even though on_add was never called on them.

I'm currently implementing a view that's similar to depth_view and I wanted to rely on this event to process new nodes (including PIs) on creation. @lee30sonia recommended to override the create_pi function and manually call on_add (many thanks for this idea!). While that provides intended behavior for my use case, it would break as soon as someone introduced a new network type that did trigger on_add events on create_pi() because it'd then process PIs twice.

Any input on this matter is welcome. Many thanks in advance!

Error in parsing benchmarks

Experiments fails while parsing benchmarks dec and mem_ctrl.

It is unclear with the problem is with the benchmarks files in the repository or the AIGER parser in mockturtle.

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x501801320)
    frame #0: 0x000000010003d186 satlut`mockturtle::aiger_reader<mockturtle::aig_network>::on_and(this=0x00007ffeefbff538, index=33, left_lit=24, right_lit=4294967260) const at aiger_reader.hpp:348:18
   345        left = _ntk.create_not( left );
   346      }
   347 
-> 348      auto right = signals[right_lit >> 1];
   349      if ( right_lit & 1 )
   350      {
   351        right = _ntk.create_not( right );

mig_algebraic_depth_rewriting_splitters::run_selective is endless

When I run mig_algebraic_depth_rewriting_splitters for c5315.v with the parameter selective, I found that the run_selective is endless.

ps_alg_rewrite.strategy = mockturtle::mig_algebraic_depth_rewriting_params::selective;
mig_algebraic_depth_rewriting_splitters(mig, ps_alg_rewrite);

And while in mockturtle::buffer_insertion::optimize can be not finished:

    while ( true )
    {
      mark_critical_paths();

      topo_view topo{ntk};
      topo.foreach_node( [this, &counter]( auto n ) {
        if ( ntk.fanout_size( n ) == 0 || ntk.value( n ) == 0 )
          return;
        if ( reduce_depth( n ) )
        {
          mark_critical_paths();
        }
        else
        {
          ++counter;
        }
      } );

      if ( counter > ntk.size() )
        break;
    }

Can you help me solve it?

Assertion `_pend != _pcuts.end()' failed.

Hello, the latest esoteric issue from me...

I have some code that looks something like:

mockturtle::cut_enumeration_params ps;
ps.cut_size = s;
ps.cut_limit = l;

const auto cuts = mockturtle::cut_enumeration<mockturtle::aig_network::node, true>(aig, ps);

I was using this with an s of 2 and 3, which seemed to work fine with an l of std::numeric_limits<decltype(ps.cut_limit)>::max() (maybe already unwise...). However, when I go beyond 3 I get an assertion failure:

foo: /home/matthew/foo/mockturtle/include/mockturtle/algorithms/../utils/cuts.hpp:482: CutType& mockturtle::cut_set<CutType, MaxCuts>::add_cut(Iterator, Iterator) [with Iterator = unsigned int*; CutType = mockturtle::cut<16, mockturtle::cut_data<true, mockturtle::empty_cut_data> >; int MaxCuts = 26]: Assertion `_pend != _pcuts.end()' failed.

The default cut_size is 4 and the default cut_limit is 26. I have confirmed that increasing either of these causes this assertion failure. I.e.:

// this fails
ps.cut_size = 4;
ps.cut_limit = 27;

// so does this
ps.cut_size = 5;
ps.cut_limit = 26;

Possibly this is specific to my graph, but I suspect I am doing something wrong in my code. Are 4 and 26 somehow pseudo max values for these fields? I could not find anything in the documentation or comments to indicate this. I am using commit 1e7f423 of mockturtle if this is relevant information.

Quality test MIG refactoring with Akers resynthesis fails

/tmp/mockturtle/test/algorithms/quality.cpp:151: FAILED:
  CHECK( v == std::vector<uint32_t>{{0, 18, 34, 22, 114, 56, 253, 113, 442, 449, 69}} )
with expansion:
  { 0, 18, 34, 22, 114, 56, 268 (0x10c), 118, 472 (0x1d8), 449 (0x1c1), 69 }
  ==
  { 0, 18, 34, 22, 114, 56, 253, 113, 442 (0x1ba), 449 (0x1c1), 69 }
/tmp/mockturtle/test/algorithms/quality.cpp:164: FAILED:
  CHECK( v2 == std::vector<uint32_t>{{0, 18, 34, 21, 115, 55, 254, 118, 443, 449, 66}} )
with expansion:
  { 0, 18, 34, 21, 115, 55, 254, 118, 447 (0x1bf), 449 (0x1c1), 66 }
  ==
  { 0, 18, 34, 21, 115, 55, 254, 118, 443 (0x1bb), 449 (0x1c1), 66 }

AIG is being transformed when read in

I think maybe the following is caused by my own misunderstanding of mockturtle, but I'm not quite sure where I've gone wrong. When I read in an AIG and attempt to programmatically traverse it, it doesn't contain exactly the gates specified in the input AIG. The network seems to have been optimized before I get a chance to interact with it.

Distilling this to a simple AAG, I'm parsing the following:

aag 18 4 0 4 14
2
4
6
8
10
23
35
36
10 6 2
12 8 2
14 6 4
16 14 12
18 17 12
20 17 14
22 21 19
24 14 12
26 8 4
28 26 24
30 29 24
32 29 26
34 33 31
36 26 24
i0 a0
i1 a1
i2 b0
i3 b1
o0 Z0
o1 Z1
o2 Z2
o3 Z3

which is the following translated AIG: small-circ.zip.

Using the C++ at the bottom of this post to view mockturtle's interpretation of this network, I get the following:

$ ./aigls small-circ.aig
aag 16 4 0 4 12
2
4
6
8
10
23
33
26
10 2 6
12 2 8
14 4 6
16 12 14
18 12 17
20 14 17
22 19 21
24 4 8
26 16 24
28 16 27
30 24 27
32 29 31

As you can see, it has fewer AND gates than the original. From node 12 onwards, it seems to have an altered understanding of the gates. Is this known behavior? Or maybe my input is somehow not canonical with respect to what mockturtle is assuming? If this is an issue with lorina rather than mockturtle, I can move it over there instead. Any help or advice would be greatly appreciated.

#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <lorina/aiger.hpp>
#include <mockturtle/mockturtle.hpp>

using net_t = mockturtle::aig_network;
using node_t = mockturtle::aig_network::node;
using signal_t = mockturtle::aig_network::signal;

int main(int argc, char **argv) {

  // validate command line arguments
  if (argc != 2 || strcmp(argv[1], "--help") == 0) {
    std::cerr << "usage: " << argv[0] << " aig_file\n"
              << " list Mockturtle's interpretation of an AIG\n";
    return EXIT_FAILURE;
  }

  // parse the input AIG into memory
  net_t aig;
  lorina::return_code rc
    = lorina::read_aiger(argv[1], mockturtle::aiger_reader(aig));
  if (rc != lorina::return_code::success) {
    std::cerr << "failed to parse " << argv[1] << "\n";
    return EXIT_FAILURE;
  }

  // print AAG header
  std::cout << "aag"
    << " " << (aig.num_pis() + aig.num_gates())
    << " " << aig.num_pis()
    << " 0" // latches (assume none)
    << " " << aig.num_pos()
    << " " << aig.num_gates()
    << "\n";

  // print inputs
  aig.foreach_pi([&](const node_t &n) {
    std::cout << (2 * aig.node_to_index(n)) << "\n";
  });

  // print outputs
  aig.foreach_po([&](const signal_t &s) {
    uint32_t index = aig.node_to_index(aig.get_node(s));
    uint32_t lsb = aig.is_complemented(s) ? 1 : 0;
    std::cout << (2 * index + lsb) << "\n";
  });

  // print gates
  aig.foreach_gate([&](const node_t &n) {
    std::cout << (2 * aig.node_to_index(n));
    aig.foreach_fanin(n, [&](const signal_t &s) {
      uint32_t index = aig.node_to_index(aig.get_node(s));
      uint32_t lsb = aig.is_complemented(s) ? 1 : 0;
      std::cout << " " << (2 * index + lsb);
    });
    std::cout << "\n";
  });

  return EXIT_SUCCESS;
}

Internal compiler error

Please have a look at the following piece of code which tries to synthesize an MIG network wrapped in a names_view from a truth table using akers_synthesis.

#include <mockturtle/networks/mig.hpp>
#include <mockturtle/views/names_view.hpp>
#include <mockturtle/algorithms/akers_synthesis.hpp>
#include <kitty/dynamic_truth_table.hpp>
#include <kitty/constructors.hpp>

int main()
{
    kitty::dynamic_truth_table tt(2);
    kitty::create_from_binary_string(tt, "0110");
    
    using named_mig = mockturtle::names_view<mockturtle::mig_network>;
    
    named_mig ntk;
    ntk = mockturtle::akers_synthesis<named_mig>(tt, tt);
}

I'm using a derivative of ubuntu 18.04 LTS and gcc/g++ 7.4.0. Trying to compile this code leads to the following error output.

./mockturtle/include/mockturtle/views/names_view.hpp:68:51: internal compiler error: in finish_member_declaration, at cp/semantics.c:3018
         current_pis.emplace_back( Ntk::make_signal( n ) );
                                   ~~~~~~~~~~~~~~~~^~~~~
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-7/README.Bugs> for instructions.

However, by combining declaration and definition of ntk in the code snippet above, it compiles and works just fine.

auto ntk = mockturtle::akers_synthesis<named_mig>(tt, tt);

Do you have any idea, what is going on here? Thanks a lot for your help!

Cut enumeration before and after node substitution in AIG

The issue is the following:

  • The number of cuts is decreasing after node substitution in AIG.
  • Node 21 (which has negated fanin 19 and negated fanin 20) is substituted with new node 54 (which has not negated fanin 19 and not negated fanin 20).
  • Attached are two pictures, one showing the AIG before substitution and the other after substituting node 21 with node 54. Also the terminal output showing the number of cuts before and after substitution.

Following is the code:

#include <mockturtle/mockturtle.hpp>
using namespace std;
int main(int argc, char *argv[])
{ 
  //AIG from file 
  mockturtle::aig_network aig;
  lorina::read_aiger("file.aig", mockturtle::aiger_reader(aig));

  //Cut enumeration parameters
  mockturtle::cut_enumeration_params cp;
  cp.cut_size = 3u;   //maximum number of leaves
  cp.cut_limit = 100u; //maximum number of computed cuts for a node

  //Cut enumeration algorithm from mockturtle
  auto cuts = mockturtle::cut_enumeration<mockturtle::aig_network, true>(aig, cp);
  cout<<"Number of cuts: "<<cuts.total_cuts()<<"\n"; 

  //Node to be substituted, index 21
  int node_index = 21;

  auto old_node = aig.index_to_node(node_index);
  auto& old_node_storage = aig._storage->nodes[old_node];
  int child0 = aig._storage->nodes[node_index].children[0u].index;
  int child1 = aig._storage->nodes[node_index].children[1u].index;
  auto child0_sig = aig.make_signal(aig.index_to_node(child0));
  auto child1_sig = aig.make_signal(aig.index_to_node(child1));
 
  //The new node we want instead of the old node
  auto new_node = aig.create_and(child0_sig, child1_sig); 

  aig.substitute_node( old_node, new_node );  
  
  cout<<"\nNode substituted...\n";
  cleanup_dangling(aig);

  cuts = mockturtle::cut_enumeration<mockturtle::aig_network, true>(aig, cp);
  cout<<"\nNumber of cuts after substitution: "<<cuts.total_cuts()<<"\n";  
}

Original AIG with node 21
Substituted 21 to 54 AIG
terminal output

Thank you in advance for any help!

Functional reduction followed by SOP balancing fails equivalence check

I found this a few days ago and haven't been able to figure out what's causing it. In most benchmarks there's no problem, but in mem_ctrl from the EPFL benchmark suite, if I apply functional reduction followed by SOP balancing to an AIG, then write the file, it's not equivalent to the original network. Either of them alone (or if I put a different optimization between them) seems to work fine.

mockturtle::aig_network run(mockturtle::aig_network &aig){
        mockturtle::sop_rebalancing<mockturtle::aig_network> balfn;
        mockturtle::balancing_params bp;
        bp.cut_enumeration_ps.cut_size = 4u;
        mockturtle::functional_reduction(aig);
        aig = mockturtle::balancing(aig, {balfn}, bp);
        return aig;
}

failing ABC cec output, in case it helps:

Verification failed for at least 62 outputs:  y153 y160 y189 ...
Output y153: Value in Network1 = 0. Value in Network2 = 1.
Input pattern:  x55=0 x92=0 x215=0 x221=0 x929=0 x216=0 x833=0 x332=0 x1144=0 x265=0 x228=0 x105=0 x153=0 x166=0 x152=0 x161=0 x234=0 x210=0 x137=0 x95=0 x479=0 x32=0 x225=0 x40=0 x72=0 x102=0 x50=0 x77=0 x88=0 x98=0 x81=0 x64=0 x65=0 x71=0 x83=0 x103=0 x67=0 x69=0 x66=0 x73=0 x45=0 x104=0 x49=0 x89=0 x48=0 x61=0 x76=0 x85=0 x106=0 x68=0 x84=0 x36=0 x82=0 x111=0 x63=0 x107=0 x94=0 x97=0 x108=0 x46=0 x86=0 x53=0 x60=0 x109=0 x110=0 x47=0 x58=0 x91=0 x90=0 x93=0 x70=0 x96=0 x35=0 x51=0 x1091=0 x957=0 x841=0 x829=0 x950=0 x1092=0 x1093=0 x146=0 x299=0 x39=0 x223=0 x222=0 x224=0 x142=0 x198=0 x189=0 x144=0 x174=0 x38=0 x100=0 x87=0 x252=0 x75=0 x54=0 x74=0 x56=0 x62=0 x59=0 x57=0

Any idea what may be causing this? Working around it is easy, but it's been bugging me.

sequential interface

sequential interface is a good start. But to be useful, it should at least support an optional "clock" and a "clock-enable". then it becomes a tuple, not just a pair of ri,ro, i.e., each ro has a supporting set of inputs. It is upto the client to decide to use these or not.

NEQ bug in aig_resub

Describe the bug
The optimized circuit was not equivalent to the original one.

To Reproduce
Version: latest (#544)

// common
#include <mockturtle/algorithms/cleanup.hpp>
#include <mockturtle/networks/aig.hpp>

// algorithm under test
#include <mockturtle/algorithms/aig_resub.hpp>
#include <mockturtle/algorithms/resubstitution.hpp>

// cec
#include <mockturtle/algorithms/equivalence_checking.hpp>
#include <mockturtle/algorithms/miter.hpp>

// io
#include <mockturtle/io/aiger_reader.hpp>
#include <mockturtle/io/write_aiger.hpp>
#include <lorina/aiger.hpp>

using namespace mockturtle;

int main()
{
  aig_network aig;
  auto res = lorina::read_aiger( "fuzz_aigresub_minimized.aig", aiger_reader( aig ) );
  aig_network aig_copy = cleanup_dangling( aig );

  resubstitution_params ps;
  ps.max_pis = 8u;
  ps.max_inserts = 5u;
  aig_resubstitution( aig, ps );
  aig = cleanup_dangling( aig );

  write_aiger( aig, "fuzz_aigresub_minimized_opt.aig" );

  auto cec = *equivalence_checking( *miter<aig_network>( aig_copy, aig ) );
  if ( !cec )
    std::cout << "NEQ\n";

  return 0;
}

fuzz_aigresub_minimized.aig.txt
(Please remove manually the .txt extension)

Environment

  • OS: Linux, MacOS
  • Compiler: c++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 / Apple clang version 13.1.6
  • Compilation mode: DEBUG

Additional context
Found by fuzz testing :)
Minimal test case produced by testcase minimizer.

Visualization
Original network
fuzz_aigresub_minimized aig dot

Optimized network
fuzz_aigresub_minimized_opt aig dot

`substitute_node`: Should it be allowed to substitute with a dead node?

The quality test (to be more specific, "Test quality improvement of MIG cut rewriting with compatibility graph and NPN4 resynthesis") does not pass anymore after the fix of #560. This is because cut_rewriting_with_compatibility_graph tries to substitute with a dead node and "revive" it. There are a few possible fixes:

  • Remove tests for cut_rewriting_with_compatibility_graph, as we already know this algorithm is buggy and is not recommended to use.
  • Modify cut_rewriting_with_compatibility_graph to skip the substitution if the replacement is dead. This will affect the quality of cut_rewriting_with_compatibility_graph, so the expected number in the quality test will also be modified. Also, is_dead needs to be implemented for klut_network.
  • Modify cut_rewriting_with_compatibility_graph to use substitute_nodes. For this, substitute_nodes needs to be implemented for other network types than AIG. With a quick experiment, this fix also affected the quality of cut_rewriting_with_compatibility_graph, and ended up in an infinite while loop in "Test quality improvement of cut rewriting with AIG NPN4 resynthesis", meaning that there might be some other problems...
  • Correctly deal with the case where the new signal is dead in substitute_node to "revive" it. This will affect other networks and algorithms, but also makes sense to some extent. So the question is: should this be allowed?

buffer_insertion::dry_run with until_sat is endless

When I insert buffer for inv6 using dry_run with the parameter until_sat , I found that the dry_run is endless.

And while in mockturtle::buffer_insertion::optimize can be not finished:

    bool updated;
    do {
      updated = find_and_move_chunks();
    } while ( updated && _ps.optimization_effort == buffer_insertion_params::until_sat );

Can you help me solve it?

The source of inv6.v:

module top( x0 , x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10 , x11 , x12 , x13 , x14 , x15 , x16 , x17 , x18 , x19 , x20 , x21 , x22 , x23 , x24 , x25 , x26 , x27 , x28 , x29 , x30 , x31 , x32 , y0 , y1 , y2 , y3 , y4 , y5 , y6 , y7 , y8 , y9 , y10 , y11 , y12 , y13 , y14 , y15 , y16 , y17 , y18 , y19 , y20 , y21 , y22 );
  input x0 , x1 , x2 , x3 , x4 , x5 , x6 , x7 , x8 , x9 , x10 , x11 , x12 , x13 , x14 , x15 , x16 , x17 , x18 , x19 , x20 , x21 , x22 , x23 , x24 , x25 , x26 , x27 , x28 , x29 , x30 , x31 , x32 ;
  output y0 , y1 , y2 , y3 , y4 , y5 , y6 , y7 , y8 , y9 , y10 , y11 , y12 , y13 , y14 , y15 , y16 , y17 , y18 , y19 , y20 , y21 , y22 ;
  wire n34 , n35 , n36 , n37 , n38 , n39 , n40 , n41 , n42 , n43 , n44 , n45 , n46 , n47 , n48 , n49 , n50 , n51 , n52 , n53 , n54 , n55 , n56 , n57 , n58 , n59 , n60 , n61 , n62 , n63 , n64 , n65 , n66 , n67 , n68 , n69 , n70 , n71 , n72 , n73 , n74 , n75 , n76 , n77 , n78 , n79 , n80 , n81 , n82 , n83 , n84 , n85 , n86 , n87 , n88 , n89 , n90 , n91 , n92 , n93 , n94 , n95 , n96 , n97 , n98 , n99 , n100 , n101 , n102 , n103 , n104 , n105 , n106 , n107 , n108 , n109 , n110 , n111 , n112 , n113 , n114 , n115 , n116 , n117 , n118 , n119 , n120 , n121 , n122 , n123 , n124 , n125 , n126 , n127 , n128 , n129 , n130 , n131 , n132 , n133 , n134 , n135 , n136 , n137 , n138 , n139 , n140 , n141 , n142 , n143 , n144 , n145 , n146 , n147 , n148 , n149 , n150 , n151 , n152 , n153 , n154 , n155 , n156 , n157 , n158 , n159 , n160 , n161 , n162 , n163 , n164 , n165 , n166 , n167 , n168 , n169 , n170 , n171 , n172 , n173 , n174 , n175 , n176 , n177 , n178 , n179 , n180 , n181 , n182 , n183 , n184 , n185 , n186 , n187 , n188 , n189 , n190 , n191 , n192 , n193 , n194 , n195 , n196 , n197 , n198 , n199 , n200 , n201 , n202 , n203 , n204 , n205 , n206 , n207 , n208 , n209 , n210 , n211 , n212 , n213 , n214 , n215 , n216 , n217 , n218 , n219 , n220 , n221 , n222 , n223 , n224 , n225 , n226 , n227 , n228 , n229 , n230 , n231 , n232 , n233 , n234 , n235 , n236 , n237 , n238 , n239 , n240 , n241 , n242 , n243 , n244 , n245 , n246 , n247 , n248 , n249 , n250 , n251 , n252 , n253 , n254 , n255 , n256 , n257 , n258 , n259 , n260 , n261 , n262 , n263 , n264 , n265 , n266 , n267 , n268 , n269 , n270 , n271 , n272 , n273 , n274 , n275 , n276 , n277 , n278 , n279 , n280 , n281 , n282 , n283 , n284 , n285 , n286 , n287 , n288 , n289 , n290 , n291 , n292 , n293 , n294 , n295 , n296 , n297 , n298 , n299 , n300 , n301 , n302 , n303 , n304 , n305 , n306 , n307 , n308 , n309 , n310 , n311 , n312 , n313 , n314 , n315 , n316 , n317 , n318 , n319 , n320 , n321 , n322 , n323 , n324 , n325 , n326 , n327 , n328 , n329 , n330 , n331 , n332 , n333 , n334 , n335 , n336 , n337 , n338 , n339 , n340 , n341 , n342 , n343 , n344 , n345 , n346 , n347 , n348 , n349 , n350 , n351 , n352 , n353 , n354 , n355 , n356 , n357 , n358 , n359 , n360 , n361 , n362 , n363 , n364 , n365 , n366 , n367 , n368 , n369 , n370 , n371 , n372 , n373 , n374 , n375 , n376 , n377 , n378 , n379 , n380 , n381 , n382 ;
  assign n34 = ~x16 & x31 ;
  assign n35 = ~x15 & n34 ;
  assign n37 = x28 & x30 ;
  assign n36 = x1 & x22 ;
  assign n38 = ( x31 & ~n36 ) | ( x31 & n37 ) | ( ~n36 & n37 ) ;
  assign n39 = n37 & ~n38 ;
  assign n40 = ( ~x0 & n35 ) | ( ~x0 & n39 ) | ( n35 & n39 ) ;
  assign n42 = x1 & x29 ;
  assign n41 = x24 & x28 ;
  assign n43 = ( x32 & ~n41 ) | ( x32 & n42 ) | ( ~n41 & n42 ) ;
  assign n44 = n42 & ~n43 ;
  assign n45 = x4 | n44 ;
  assign n46 = x32 & ~n45 ;
  assign n47 = ( ~x0 & n44 ) | ( ~x0 & n46 ) | ( n44 & n46 ) ;
  assign n48 = ~x0 & x3 ;
  assign n49 = ( x28 & x30 ) | ( x28 & n48 ) | ( x30 & n48 ) ;
  assign n50 = n48 & ~n49 ;
  assign n51 = x29 & ~x30 ;
  assign n52 = ~x0 & x28 ;
  assign n53 = ( x0 & n51 ) | ( x0 & ~n52 ) | ( n51 & ~n52 ) ;
  assign n54 = ( x0 & x3 ) | ( x0 & n53 ) | ( x3 & n53 ) ;
  assign n80 = x0 | x28 ;
  assign n58 = x11 | x12 ;
  assign n55 = ( x12 & x21 ) | ( x12 & x29 ) | ( x21 & x29 ) ;
  assign n56 = ( ~x12 & x20 ) | ( ~x12 & x29 ) | ( x20 & x29 ) ;
  assign n57 = n55 & n56 ;
  assign n59 = ( x19 & n57 ) | ( x19 & ~n58 ) | ( n57 & ~n58 ) ;
  assign n60 = ( ~x11 & n58 ) | ( ~x11 & n59 ) | ( n58 & n59 ) ;
  assign n61 = n58 & n60 ;
  assign n66 = ( ~x9 & x10 ) | ( ~x9 & n61 ) | ( x10 & n61 ) ;
  assign n62 = x11 & ~x29 ;
  assign n63 = ( x11 & ~x21 ) | ( x11 & n62 ) | ( ~x21 & n62 ) ;
  assign n64 = ( ~x11 & x12 ) | ( ~x11 & n63 ) | ( x12 & n63 ) ;
  assign n65 = ( ~x12 & n58 ) | ( ~x12 & n64 ) | ( n58 & n64 ) ;
  assign n67 = ( x9 & x10 ) | ( x9 & ~n65 ) | ( x10 & ~n65 ) ;
  assign n68 = n66 & n67 ;
  assign n69 = x11 & ~x12 ;
  assign n70 = ~x9 & x10 ;
  assign n71 = ( x9 & n69 ) | ( x9 & ~n70 ) | ( n69 & ~n70 ) ;
  assign n75 = x19 & x20 ;
  assign n72 = x10 & ~x11 ;
  assign n73 = ~x12 & n72 ;
  assign n74 = ( ~x10 & x29 ) | ( ~x10 & n73 ) | ( x29 & n73 ) ;
  assign n76 = ( x21 & n74 ) | ( x21 & ~n75 ) | ( n74 & ~n75 ) ;
  assign n77 = n75 & n76 ;
  assign n78 = x9 & ~n77 ;
  assign n79 = ( n68 & n71 ) | ( n68 & ~n78 ) | ( n71 & ~n78 ) ;
  assign n81 = ( x30 & n79 ) | ( x30 & n80 ) | ( n79 & n80 ) ;
  assign n82 = ~n80 & n81 ;
  assign n101 = x0 | x16 ;
  assign n83 = x1 & x23 ;
  assign n90 = x28 & n83 ;
  assign n84 = x15 & ~x17 ;
  assign n85 = x7 & ~x17 ;
  assign n86 = ( x6 & x15 ) | ( x6 & ~n85 ) | ( x15 & ~n85 ) ;
  assign n87 = ( x17 & n84 ) | ( x17 & ~n86 ) | ( n84 & ~n86 ) ;
  assign n88 = x15 & x17 ;
  assign n89 = ~x14 & n88 ;
  assign n91 = ( n87 & n89 ) | ( n87 & n90 ) | ( n89 & n90 ) ;
  assign n92 = n90 & n91 ;
  assign n95 = ~x14 & x15 ;
  assign n96 = ( ~x17 & x28 ) | ( ~x17 & n95 ) | ( x28 & n95 ) ;
  assign n97 = n95 & ~n96 ;
  assign n93 = ( x11 & x12 ) | ( x11 & n70 ) | ( x12 & n70 ) ;
  assign n94 = n70 & ~n93 ;
  assign n98 = ~n92 & n94 ;
  assign n99 = n97 & n98 ;
  assign n100 = ( x30 & n92 ) | ( x30 & n99 ) | ( n92 & n99 ) ;
  assign n102 = ( ~x18 & n100 ) | ( ~x18 & n101 ) | ( n100 & n101 ) ;
  assign n103 = ~n101 & n102 ;
  assign n114 = x1 & ~x9 ;
  assign n111 = ~x10 & x11 ;
  assign n104 = x23 & ~x28 ;
  assign n105 = ~x16 & n104 ;
  assign n106 = x6 | x8 ;
  assign n107 = x18 & ~n106 ;
  assign n108 = ( x6 & x17 ) | ( x6 & n107 ) | ( x17 & n107 ) ;
  assign n109 = x17 | x18 ;
  assign n110 = ( n105 & n108 ) | ( n105 & ~n109 ) | ( n108 & ~n109 ) ;
  assign n112 = ( x12 & n110 ) | ( x12 & ~n111 ) | ( n110 & ~n111 ) ;
  assign n113 = n111 & n112 ;
  assign n115 = ( x30 & n113 ) | ( x30 & ~n114 ) | ( n113 & ~n114 ) ;
  assign n116 = n114 & n115 ;
  assign n121 = ~x16 & x17 ;
  assign n122 = x16 & x18 ;
  assign n123 = x17 & x18 ;
  assign n124 = ( x6 & x17 ) | ( x6 & n123 ) | ( x17 & n123 ) ;
  assign n125 = ( n121 & n122 ) | ( n121 & ~n124 ) | ( n122 & ~n124 ) ;
  assign n117 = ( x28 & n58 ) | ( x28 & n70 ) | ( n58 & n70 ) ;
  assign n118 = n70 & ~n117 ;
  assign n119 = x28 | n118 ;
  assign n120 = ( n83 & n118 ) | ( n83 & n119 ) | ( n118 & n119 ) ;
  assign n126 = ( x30 & n120 ) | ( x30 & ~n125 ) | ( n120 & ~n125 ) ;
  assign n127 = ( n116 & n125 ) | ( n116 & n126 ) | ( n125 & n126 ) ;
  assign n128 = ~x15 & n127 ;
  assign n129 = ~x0 & n128 ;
  assign n131 = x1 & x18 ;
  assign n130 = x0 | x15 ;
  assign n132 = ( ~x22 & n130 ) | ( ~x22 & n131 ) | ( n130 & n131 ) ;
  assign n133 = n131 & ~n132 ;
  assign n134 = ( x18 & n118 ) | ( x18 & n130 ) | ( n118 & n130 ) ;
  assign n135 = ~n130 & n134 ;
  assign n136 = ( n119 & n133 ) | ( n119 & n135 ) | ( n133 & n135 ) ;
  assign n137 = x15 & ~x18 ;
  assign n144 = x1 & n137 ;
  assign n138 = ( x22 & x28 ) | ( x22 & ~n137 ) | ( x28 & ~n137 ) ;
  assign n139 = x9 | x10 ;
  assign n140 = ~x28 & n139 ;
  assign n141 = ( ~x22 & n137 ) | ( ~x22 & n140 ) | ( n137 & n140 ) ;
  assign n142 = x11 & x12 ;
  assign n143 = ( n138 & ~n141 ) | ( n138 & n142 ) | ( ~n141 & n142 ) ;
  assign n145 = ~n136 & n143 ;
  assign n146 = n144 & n145 ;
  assign n147 = ( x30 & n136 ) | ( x30 & n146 ) | ( n136 & n146 ) ;
  assign n148 = ~x17 & n147 ;
  assign n149 = ( x0 & n101 ) | ( x0 & n148 ) | ( n101 & n148 ) ;
  assign n150 = x1 & ~x6 ;
  assign n151 = ( ~x8 & x10 ) | ( ~x8 & n150 ) | ( x10 & n150 ) ;
  assign n152 = n150 & ~n151 ;
  assign n153 = ~x17 & x22 ;
  assign n154 = x16 & n153 ;
  assign n155 = ( ~n142 & n152 ) | ( ~n142 & n154 ) | ( n152 & n154 ) ;
  assign n156 = n142 & n155 ;
  assign n157 = ~x0 & n156 ;
  assign n158 = ( ~x14 & x17 ) | ( ~x14 & n156 ) | ( x17 & n156 ) ;
  assign n159 = ( x0 & ~x16 ) | ( x0 & n158 ) | ( ~x16 & n158 ) ;
  assign n160 = ( ~x0 & n157 ) | ( ~x0 & n159 ) | ( n157 & n159 ) ;
  assign n161 = x10 & ~n58 ;
  assign n162 = ( n157 & n160 ) | ( n157 & n161 ) | ( n160 & n161 ) ;
  assign n163 = x28 & n36 ;
  assign n164 = ( x16 & x17 ) | ( x16 & ~n163 ) | ( x17 & ~n163 ) ;
  assign n165 = n163 & ~n164 ;
  assign n166 = x9 | x28 ;
  assign n167 = ( x30 & n165 ) | ( x30 & ~n166 ) | ( n165 & ~n166 ) ;
  assign n168 = ( x16 & x17 ) | ( x16 & ~n58 ) | ( x17 & ~n58 ) ;
  assign n169 = n58 | n168 ;
  assign n170 = ~x6 & x7 ;
  assign n171 = ( x28 & n70 ) | ( x28 & ~n170 ) | ( n70 & ~n170 ) ;
  assign n172 = n70 & ~n171 ;
  assign n173 = ~n169 & n172 ;
  assign n174 = ( x30 & n165 ) | ( x30 & n173 ) | ( n165 & n173 ) ;
  assign n175 = ( n162 & n167 ) | ( n162 & n174 ) | ( n167 & n174 ) ;
  assign n176 = ~x18 & n175 ;
  assign n177 = x15 & n176 ;
  assign n178 = x0 | n177 ;
  assign n179 = x0 & x7 ;
  assign n200 = x16 | x18 ;
  assign n180 = x22 & x28 ;
  assign n181 = x1 & n180 ;
  assign n185 = ( ~x15 & x17 ) | ( ~x15 & n170 ) | ( x17 & n170 ) ;
  assign n186 = n170 & ~n185 ;
  assign n182 = ( ~x6 & x15 ) | ( ~x6 & x17 ) | ( x15 & x17 ) ;
  assign n183 = ( x14 & x15 ) | ( x14 & ~x17 ) | ( x15 & ~x17 ) ;
  assign n184 = n182 & ~n183 ;
  assign n187 = n184 & ~n186 ;
  assign n188 = ~x0 & n187 ;
  assign n189 = ( n181 & n186 ) | ( n181 & n188 ) | ( n186 & n188 ) ;
  assign n190 = x12 | x14 ;
  assign n196 = x30 & ~n190 ;
  assign n191 = x15 & ~x28 ;
  assign n192 = ( x17 & n190 ) | ( x17 & n191 ) | ( n190 & n191 ) ;
  assign n193 = x0 | x9 ;
  assign n194 = ( x10 & ~x11 ) | ( x10 & n193 ) | ( ~x11 & n193 ) ;
  assign n195 = ~n193 & n194 ;
  assign n197 = ( n192 & n195 ) | ( n192 & ~n196 ) | ( n195 & ~n196 ) ;
  assign n198 = n196 & n197 ;
  assign n199 = ( x30 & n189 ) | ( x30 & n198 ) | ( n189 & n198 ) ;
  assign n201 = n179 | n199 ;
  assign n202 = ( n179 & ~n200 ) | ( n179 & n201 ) | ( ~n200 & n201 ) ;
  assign n232 = ~n58 & n70 ;
  assign n228 = ( ~x28 & n58 ) | ( ~x28 & n122 ) | ( n58 & n122 ) ;
  assign n215 = x15 & ~x16 ;
  assign n226 = ( x18 & ~n170 ) | ( x18 & n215 ) | ( ~n170 & n215 ) ;
  assign n227 = n215 & ~n226 ;
  assign n229 = ( ~x28 & n58 ) | ( ~x28 & n227 ) | ( n58 & n227 ) ;
  assign n230 = n130 & ~n227 ;
  assign n231 = ( n228 & n229 ) | ( n228 & ~n230 ) | ( n229 & ~n230 ) ;
  assign n233 = n179 | n231 ;
  assign n234 = ( n179 & n232 ) | ( n179 & n233 ) | ( n232 & n233 ) ;
  assign n203 = x7 & ~x15 ;
  assign n204 = ( x16 & x28 ) | ( x16 & n203 ) | ( x28 & n203 ) ;
  assign n205 = n203 & ~n204 ;
  assign n206 = ( x0 & ~x12 ) | ( x0 & n111 ) | ( ~x12 & n111 ) ;
  assign n207 = ( ~x15 & x16 ) | ( ~x15 & n106 ) | ( x16 & n106 ) ;
  assign n208 = ( x0 & x15 ) | ( x0 & ~x28 ) | ( x15 & ~x28 ) ;
  assign n209 = x6 & ~x16 ;
  assign n210 = ( x0 & ~x28 ) | ( x0 & n209 ) | ( ~x28 & n209 ) ;
  assign n211 = ( n207 & n208 ) | ( n207 & n210 ) | ( n208 & n210 ) ;
  assign n212 = ( x12 & ~n111 ) | ( x12 & n211 ) | ( ~n111 & n211 ) ;
  assign n213 = ( n205 & ~n206 ) | ( n205 & n212 ) | ( ~n206 & n212 ) ;
  assign n214 = n111 & n213 ;
  assign n216 = ( x28 & n170 ) | ( x28 & ~n215 ) | ( n170 & ~n215 ) ;
  assign n217 = n215 & n216 ;
  assign n218 = n214 & ~n217 ;
  assign n219 = ~x9 & n218 ;
  assign n220 = ( ~x28 & n122 ) | ( ~x28 & n130 ) | ( n122 & n130 ) ;
  assign n221 = n122 & ~n220 ;
  assign n222 = ( ~x18 & n36 ) | ( ~x18 & n221 ) | ( n36 & n221 ) ;
  assign n223 = n36 & n222 ;
  assign n224 = ( n36 & n217 ) | ( n36 & n221 ) | ( n217 & n221 ) ;
  assign n225 = n36 & n224 ;
  assign n235 = ( n219 & n223 ) | ( n219 & n225 ) | ( n223 & n225 ) ;
  assign n236 = n234 | n235 ;
  assign n237 = ~x17 & x30 ;
  assign n238 = ( n179 & n236 ) | ( n179 & n237 ) | ( n236 & n237 ) ;
  assign n242 = x1 & ~x10 ;
  assign n239 = x12 & ~x16 ;
  assign n240 = ( x17 & x23 ) | ( x17 & ~n239 ) | ( x23 & ~n239 ) ;
  assign n241 = n239 & n240 ;
  assign n243 = ( x11 & n241 ) | ( x11 & ~n242 ) | ( n241 & ~n242 ) ;
  assign n244 = n242 & n243 ;
  assign n245 = x16 & ~x17 ;
  assign n246 = ( x28 & ~n161 ) | ( x28 & n245 ) | ( ~n161 & n245 ) ;
  assign n247 = n245 & ~n246 ;
  assign n248 = ( ~x9 & n244 ) | ( ~x9 & n247 ) | ( n244 & n247 ) ;
  assign n249 = x18 & x30 ;
  assign n250 = ~x15 & n249 ;
  assign n251 = ( x16 & x17 ) | ( x16 & ~x23 ) | ( x17 & ~x23 ) ;
  assign n252 = ( x16 & x17 ) | ( x16 & x28 ) | ( x17 & x28 ) ;
  assign n253 = ~n251 & n252 ;
  assign n254 = ~n248 & n253 ;
  assign n255 = x1 & n254 ;
  assign n256 = ( n248 & n250 ) | ( n248 & n255 ) | ( n250 & n255 ) ;
  assign n257 = ~x0 & n256 ;
  assign n258 = x0 & ~x7 ;
  assign n259 = n257 | n258 ;
  assign n267 = x6 | x15 ;
  assign n260 = x1 & ~x8 ;
  assign n261 = ( x10 & ~x23 ) | ( x10 & n260 ) | ( ~x23 & n260 ) ;
  assign n262 = n260 & ~n261 ;
  assign n263 = ( x18 & ~n142 ) | ( x18 & n262 ) | ( ~n142 & n262 ) ;
  assign n264 = n142 & n263 ;
  assign n265 = ( x12 & x18 ) | ( x12 & n72 ) | ( x18 & n72 ) ;
  assign n266 = n72 & ~n265 ;
  assign n268 = ( n264 & n266 ) | ( n264 & ~n267 ) | ( n266 & ~n267 ) ;
  assign n269 = ~n267 & n268 ;
  assign n270 = ( x18 & n95 ) | ( x18 & ~n161 ) | ( n95 & ~n161 ) ;
  assign n271 = n95 & ~n270 ;
  assign n272 = ( ~n166 & n269 ) | ( ~n166 & n271 ) | ( n269 & n271 ) ;
  assign n273 = ~n166 & n272 ;
  assign n274 = ( x15 & x18 ) | ( x15 & ~n90 ) | ( x18 & ~n90 ) ;
  assign n275 = n90 & ~n274 ;
  assign n276 = ( x30 & n273 ) | ( x30 & n275 ) | ( n273 & n275 ) ;
  assign n277 = ( n121 & n179 ) | ( n121 & n276 ) | ( n179 & n276 ) ;
  assign n278 = ( x0 & ~n179 ) | ( x0 & n277 ) | ( ~n179 & n277 ) ;
  assign n279 = ~n179 & n278 ;
  assign n280 = x24 & ~x25 ;
  assign n281 = ~x0 & n280 ;
  assign n282 = ( x25 & x29 ) | ( x25 & n281 ) | ( x29 & n281 ) ;
  assign n283 = x28 & n282 ;
  assign n284 = x0 | x1 ;
  assign n285 = ( x0 & n283 ) | ( x0 & n284 ) | ( n283 & n284 ) ;
  assign n286 = ~x0 & x1 ;
  assign n287 = ( ~x13 & x22 ) | ( ~x13 & n286 ) | ( x22 & n286 ) ;
  assign n288 = n286 & ~n287 ;
  assign n289 = ( x29 & ~n41 ) | ( x29 & n288 ) | ( ~n41 & n288 ) ;
  assign n290 = n41 & n289 ;
  assign n292 = x1 & x28 ;
  assign n291 = ~x0 & x24 ;
  assign n293 = ( x29 & n291 ) | ( x29 & ~n292 ) | ( n291 & ~n292 ) ;
  assign n294 = n292 & n293 ;
  assign n295 = x5 | x22 ;
  assign n296 = ( x5 & n37 ) | ( x5 & n295 ) | ( n37 & n295 ) ;
  assign n297 = ~x0 & n296 ;
  assign n298 = ( ~x28 & x30 ) | ( ~x28 & n58 ) | ( x30 & n58 ) ;
  assign n299 = ~n58 & n298 ;
  assign n300 = ( x10 & n193 ) | ( x10 & n299 ) | ( n193 & n299 ) ;
  assign n301 = ~n193 & n300 ;
  assign n302 = x26 & ~x27 ;
  assign n303 = x3 & n302 ;
  assign n304 = ( x26 & n301 ) | ( x26 & ~n303 ) | ( n301 & ~n303 ) ;
  assign n305 = x0 | n304 ;
  assign n306 = x3 & x27 ;
  assign n307 = ( x3 & x26 ) | ( x3 & n306 ) | ( x26 & n306 ) ;
  assign n308 = ( n301 & ~n306 ) | ( n301 & n307 ) | ( ~n306 & n307 ) ;
  assign n309 = ( x27 & ~n306 ) | ( x27 & n308 ) | ( ~n306 & n308 ) ;
  assign n310 = x0 | n309 ;
  assign n311 = ~x28 & x30 ;
  assign n312 = ~x0 & n311 ;
  assign n313 = x10 | x12 ;
  assign n314 = x9 | n313 ;
  assign n315 = x12 & x21 ;
  assign n316 = ( x9 & x29 ) | ( x9 & n315 ) | ( x29 & n315 ) ;
  assign n317 = ( x12 & x19 ) | ( x12 & x21 ) | ( x19 & x21 ) ;
  assign n318 = ( ~x12 & x19 ) | ( ~x12 & x20 ) | ( x19 & x20 ) ;
  assign n319 = n317 & n318 ;
  assign n320 = ( ~x9 & x29 ) | ( ~x9 & n319 ) | ( x29 & n319 ) ;
  assign n321 = n316 & n320 ;
  assign n322 = x10 & n321 ;
  assign n323 = ( x11 & ~n314 ) | ( x11 & n322 ) | ( ~n314 & n322 ) ;
  assign n324 = x12 | n77 ;
  assign n325 = ( n72 & n77 ) | ( n72 & n324 ) | ( n77 & n324 ) ;
  assign n326 = x9 & ~n323 ;
  assign n327 = n325 & n326 ;
  assign n328 = ( n312 & n323 ) | ( n312 & n327 ) | ( n323 & n327 ) ;
  assign n332 = x3 & ~x29 ;
  assign n333 = x30 | n332 ;
  assign n335 = x10 & x11 ;
  assign n334 = x21 & x29 ;
  assign n336 = ( x12 & n334 ) | ( x12 & ~n335 ) | ( n334 & ~n335 ) ;
  assign n337 = n335 & n336 ;
  assign n349 = ( x9 & x30 ) | ( x9 & ~n337 ) | ( x30 & ~n337 ) ;
  assign n341 = ~x11 & x12 ;
  assign n338 = ~x12 & x19 ;
  assign n339 = ( x21 & x29 ) | ( x21 & ~n338 ) | ( x29 & ~n338 ) ;
  assign n340 = n338 & n339 ;
  assign n342 = ( x10 & ~x11 ) | ( x10 & n340 ) | ( ~x11 & n340 ) ;
  assign n343 = ( x11 & n341 ) | ( x11 & n342 ) | ( n341 & n342 ) ;
  assign n346 = ~x10 & n334 ;
  assign n344 = ( x11 & ~x12 ) | ( x11 & n75 ) | ( ~x12 & n75 ) ;
  assign n345 = n75 & n344 ;
  assign n347 = n343 | n345 ;
  assign n348 = ( n343 & n346 ) | ( n343 & n347 ) | ( n346 & n347 ) ;
  assign n350 = ( x9 & ~x30 ) | ( x9 & n348 ) | ( ~x30 & n348 ) ;
  assign n351 = n349 & ~n350 ;
  assign n329 = ( x3 & x29 ) | ( x3 & x30 ) | ( x29 & x30 ) ;
  assign n330 = ( x2 & x29 ) | ( x2 & ~x30 ) | ( x29 & ~x30 ) ;
  assign n331 = ~n329 & n330 ;
  assign n352 = x28 | n331 ;
  assign n353 = ( n333 & ~n351 ) | ( n333 & n352 ) | ( ~n351 & n352 ) ;
  assign n354 = ( x0 & ~x28 ) | ( x0 & n353 ) | ( ~x28 & n353 ) ;
  assign n370 = ( x3 & ~x28 ) | ( x3 & x30 ) | ( ~x28 & x30 ) ;
  assign n371 = ~x0 & n370 ;
  assign n358 = ( x11 & ~x12 ) | ( x11 & n139 ) | ( ~x12 & n139 ) ;
  assign n359 = ~n139 & n358 ;
  assign n355 = x9 & x12 ;
  assign n356 = ( x21 & x29 ) | ( x21 & ~n355 ) | ( x29 & ~n355 ) ;
  assign n357 = n355 & n356 ;
  assign n360 = n75 & n357 ;
  assign n361 = ( ~x10 & n359 ) | ( ~x10 & n360 ) | ( n359 & n360 ) ;
  assign n364 = ~x12 & x21 ;
  assign n365 = ~x11 & n364 ;
  assign n366 = ( ~n111 & n142 ) | ( ~n111 & n365 ) | ( n142 & n365 ) ;
  assign n367 = x9 & n366 ;
  assign n362 = x20 & x29 ;
  assign n363 = x19 & n362 ;
  assign n368 = n361 | n363 ;
  assign n369 = ( n361 & n367 ) | ( n361 & n368 ) | ( n367 & n368 ) ;
  assign n372 = ( x28 & x30 ) | ( x28 & ~n369 ) | ( x30 & ~n369 ) ;
  assign n373 = n371 & ~n372 ;
  assign n380 = ~x28 & x29 ;
  assign n377 = x12 & x19 ;
  assign n374 = ~x0 & x9 ;
  assign n375 = ( x10 & x11 ) | ( x10 & ~n374 ) | ( x11 & ~n374 ) ;
  assign n376 = n374 & n375 ;
  assign n378 = ( x20 & n376 ) | ( x20 & ~n377 ) | ( n376 & ~n377 ) ;
  assign n379 = n377 & n378 ;
  assign n381 = ( x30 & n379 ) | ( x30 & ~n380 ) | ( n379 & ~n380 ) ;
  assign n382 = n380 & n381 ;
  assign y0 = n40 ;
  assign y1 = n47 ;
  assign y2 = n50 ;
  assign y3 = n54 ;
  assign y4 = n82 ;
  assign y5 = n103 ;
  assign y6 = n129 ;
  assign y7 = n149 ;
  assign y8 = n178 ;
  assign y9 = n202 ;
  assign y10 = n238 ;
  assign y11 = n259 ;
  assign y12 = n279 ;
  assign y13 = n285 ;
  assign y14 = n290 ;
  assign y15 = n294 ;
  assign y16 = n297 ;
  assign y17 = n305 ;
  assign y18 = n310 ;
  assign y19 = n328 ;
  assign y20 = n354 ;
  assign y21 = n373 ;
  assign y22 = n382 ;
endmodule

Failing Windows builds using different toolsets (#530)

Describe the bug
When compiling with different toolsets under Windows, it becomes apparent that certain constructs do not compile.

To Reproduce
To be seen in #530.

Environment

  • OS: Windows
  • Compiler: Visual Studio 16 2019 with the v142 toolset
  • Compilation mode: RELEASE

Additional context
I suspect this to be the tip of the iceberg, unfortunately, as I had some further issues down the road when compiling any code involving bill under Windows with the v142 toolset. It would always complain that it misses __sync_bool_compare_and_swap in glucose.hpp (the actual solver). However, that will be a different issue. I would be glad to assist in the process of fixing these problems.

Check list

  • I have tried to run in DEBUG mode and there was no assertion failure (or the reported bug is an assertion failure).
  • I have made sure that the provided code compiles and reproduces the error.

Bug in akers_synthesis (known)

Describe the bug
There has been a known bug that mockturtle/algorithms/akers_synthesis.hpp produces incorrect results for some functions.

To Reproduce
Failing test case:

TEST_CASE( "Akers regressions", "[akers_synthesis]" )
{
  for ( std::string const& function : std::vector<std::string>{ "0000", "3333", "5555", "aaaa", "cccc", "f0f0", "0f0f", "ffff" } )
  {
    kitty::dynamic_truth_table f( 4 ), care( 4 );
    create_from_hex_string( f, function );
    for ( auto i = 0u; i < unsigned( f.num_bits() ); i++ )
    {
      set_bit( care, i );
    }

    std::vector<kitty::dynamic_truth_table> xs{6, kitty::dynamic_truth_table( 4 )};
    xs[0] = f;
    xs[1] = care;
    kitty::create_nth_var( xs[2], 0 );
    kitty::create_nth_var( xs[3], 1 );
    kitty::create_nth_var( xs[4], 2 );
    kitty::create_nth_var( xs[5], 3 );

    mig_network mig = akers_synthesis<mig_network>( f, care );
    if ( mig.size() > 4 )
    {
      mig.foreach_gate( [&]( auto n ) {
        std::vector<kitty::dynamic_truth_table> fanin{3, kitty::dynamic_truth_table( 4 )};
        mig.foreach_fanin( n, [&]( auto s, auto j ) {
          if ( mig.node_to_index( mig.get_node( s ) ) == 0 )
          {
            fanin[j] = ~xs[1];
          }
          else
          {
            fanin[j] = xs[mig.node_to_index( mig.get_node( s ) ) + 1];
          }
        } );
        xs.push_back( mig.compute( n, fanin.begin(), fanin.end() ) );
      } );

      mig.foreach_po( [&]( auto s ){
        if ( mig.is_complemented( s ) )
        {
          CHECK( ~xs[xs.size() - 1] == f );
        }
        else
        {
          CHECK( xs[xs.size() - 1] == f );
        }
      });
    }
  }
}

Additional context
This implementation of the Akers majority synthesis algorithm has been modified from the original paper [1]. An exact re-implementation of the Akers algorithm can be found in mockturtle/algorithms/resyn_engines/mig_resyn.hpp. However, it is advised to use mig_resyn_topdown instead, as this is more efficient. [2]

This issue will not be worked on and is only for documentation purpose.

[1] Akers, S. B. (1962, October). Synthesis of combinational logic using three-input majority gates. In 3rd Annual Symposium on Switching Circuit Theory and Logical Design (SWCT 1962) (pp. 149-158). IEEE.
[2] S.-Y. Lee, H. Riener and G. D. Micheli, "Logic Resynthesis of Majority-Based Circuits by Top-Down Decomposition," 2021 24th International Symposium on Design and Diagnostics of Electronic Circuits & Systems (DDECS), 2021

Use parallel-hashmap instead of sparsepp

While trying to fix some warnings on my side, I found that the author of sparsepp recommends the use of his new header-only library parallel-hashmap: https://github.com/greg7mdp/parallel-hashmap

I suppose the change should be straightforward.

I'm not sure how much of an impact it would make on mockturtle performance, but the author says that parallel-hashmap is significantly faster.

incorrect description of fan in limit in reconvergence cut algo

include/mockturtle/algorithms/reconv_cut2.hpp contains the following:

  /* \brief limit on the size of the supernode */
  int node_size_max;

  /* \brief limit on the size of the supernode */
  int node_fan_stop;

I think the comment on the second of these is meant to refer to a fan-in limit.

Refactoring: aiger_reader NameMap

The implementation of aiger_reader takes a network and optionally a NameMap as parameters. The second parameter is used to store the signal names from the AIGER file.
However, the optional parameter can be avoided by decorating the network with a names_view.

bug with assumptions in cnf_view

A test case that fails:

TEST_CASE( "bug in assumptions", "[cnf_view]" )
{
  cnf_view<xag_network> xag;
  const auto a = xag.create_pi();
  const auto b = xag.create_pi();

  const auto f = xag.create_xor( a, b );
  const auto g = xag.create_xor( f, f );

  /* if delete the following 4 lines, this test case will pass */
  bill::result::clause_type assump1( 1, xag.lit(f) );
  const auto result1 = xag.solve( assump1 );
  CHECK( result1 );   /* has result */
  CHECK( *result1 ); /* result is SAT */

  bill::result::clause_type assump2( 1, xag.lit(g) );
  const auto result2 = xag.solve( assump2 );
  CHECK( result2 );   /* has result */
  CHECK( !*result2 ); /* result is UNSAT */ /* this check fails */
}

Bug in node_map

lines 258 and 281 should be has( n ) and has( ntk.get_node( f ) ), respectively

cell_window.num_pis() vs. foreach_cell_fanin

Hello,

I'm trying to create a cell mapping for a network to process each cell. Please consider the following code snippet.

template<class Ntk>
void print_cell_io( Ntk const& ntk )   // ntk is a mapped network
{
  auto cells = mockturtle::cell_window( ntk );

  ntk.foreach_node( [&]( auto const n ) {
    if ( ntk.is_constant( n ) || ntk.is_pi( n ) || !ntk.is_cell_root( n ) )
      return;

    auto fanin_counter = 0u;
    ntk.foreach_cell_fanin( n, [&]( auto const f ) {
      ++fanin_counter;
    } );

    std::cout << "cell has " << fanin_counter << " fanins\n";

    cells.compute_window_for( n );
    std::cout << "cell_window i/o = " << cells.num_pis() << "/" << cells.num_pos() << "\n";
  } );
}

As I've understood the documentation about mappings, a cell has a single root (i.e. one primary output?). So I assumed the cell_fanins to be the primary inputs of the cell. When executing the above code in CirKit with e.g. AIG networks, the cell_fanins don't match the cell_window I/Os. Additionally, cell_windows can have multiple outputs.

May I ask you to clarify the difference between the cell mapping and the cell_window applied to it? How do I process cells correctly? How do I access their I/Os, their contained nodes, etc.?

Thanks a lot for your help!

how to remove constant nodes from mapped network

Dears,

I'm playing with the mockturtle library in these days and I found something for me unexpected.
It looks that lut_mapping may produce LUT with 0x0 as functionality.
For example for this bench

INPUT(n2)
INPUT(n4)
INPUT(n6)
INPUT(n7)
INPUT(n8)
INPUT(n10)
INPUT(n12)
INPUT(n13)
INPUT(n14)
INPUT(n18)
INPUT(n20)
INPUT(n22)
OUTPUT(po0)
OUTPUT(po1)
OUTPUT(po2)
OUTPUT(po3)
OUTPUT(po4)
OUTPUT(po5)
OUTPUT(po6)
OUTPUT(po7)
OUTPUT(po8)
OUTPUT(po9)
OUTPUT(po10)
OUTPUT(po11)
OUTPUT(po12)
OUTPUT(po13)
OUTPUT(po14)
OUTPUT(po15)
OUTPUT(po16)
OUTPUT(po17)
OUTPUT(po18)
OUTPUT(po19)
OUTPUT(po20)
OUTPUT(po21)
n0 = gnd
n1 = vdd
n3 = LUT 0x1 (n2)
n5 = LUT 0x2 (n4)
n9 = LUT 0x1000 (n2, n6, n7, n8)
n11 = LUT 0x2 (n6, n10)
n15 = LUT 0x00008000 (n6, n10, n12, n13, n14)
n16 = LUT 0x8000000000000000 (n6, n10, n12, n13, n14, n0)
n17 = LUT 0xa2222222 (n6, n10, n12, n13, n14)
n19 = LUT 0x1 (n18)
n21 = LUT 0x8 (n18, n20)
n23 = LUT 0x02 (n6, n10, n22)
n24 = LUT 0x0000000000008000 (n6, n10, n12, n13, n14, n22)
n25 = LUT 0x4000000000000000 (n22, n6, n10, n12, n13, n14)
n26 = LUT 0x8 (n0, n25)
n27 = LUT 0x0800 (n12, n13, n14, n22)
n28 = LUT 0x80000000 (n22, n12, n13, n14, n0)
n29 = LUT 0xf000000080000000 (n6, n10, n12, n13, n14, n22)
n30 = LUT 0x00000000 (n6, n10, n12, n13, n14)
n31 = LUT 0x08880888 (n6, n10, n12, n13, n14)
n32 = LUT 0x0 (n14)
n33 = LUT 0x10 (n2, n6, n7)
n34 = LUT 0xfffffffc (n8, n15, n17, n30, n33)
n35 = LUT 0xffffffff08880888 (n6, n10, n12, n13, n32, n34)
n36 = LUT 0x0000000000000000 (n6, n10, n12, n13, n14, n22)
n37 = LUT 0x0000000008880888 (n6, n10, n12, n13, n14, n22)
n38 = LUT 0x0000 (n12, n13, n14, n22)
n39 = LUT 0x7700 (n12, n13, n14, n22)
po0 = LUT 0x2 (n3)
po1 = LUT 0x2 (n5)
po2 = LUT 0x2 (n9)
po3 = LUT 0x2 (n11)
po4 = LUT 0x2 (n15)
po5 = LUT 0x2 (n16)
po6 = LUT 0x2 (n17)
po7 = LUT 0x2 (n19)
po8 = LUT 0x2 (n21)
po9 = LUT 0x2 (n23)
po10 = LUT 0x2 (n24)
po11 = LUT 0x2 (n26)
po12 = LUT 0x2 (n27)
po13 = LUT 0x2 (n28)
po14 = LUT 0x2 (n29)
po15 = LUT 0x2 (n30)
po16 = LUT 0x2 (n31)
po17 = LUT 0x2 (n35)
po18 = LUT 0x2 (n36)
po19 = LUT 0x2 (n37)
po20 = LUT 0x2 (n38)
po21 = LUT 0x2 (n39)

I've got something like:

INPUT(n2)
INPUT(n3)
INPUT(n4)
INPUT(n5)
INPUT(n6)
INPUT(n7)
INPUT(n8)
INPUT(n9)
INPUT(n10)
INPUT(n11)
INPUT(n12)
INPUT(n13)
OUTPUT(po0)
OUTPUT(po1)
OUTPUT(po2)
OUTPUT(po3)
OUTPUT(po4)
OUTPUT(po5)
OUTPUT(po6)
OUTPUT(po7)
OUTPUT(po8)
OUTPUT(po9)
OUTPUT(po10)
OUTPUT(po11)
OUTPUT(po12)
OUTPUT(po13)
OUTPUT(po14)
OUTPUT(po15)
OUTPUT(po16)
OUTPUT(po17)
OUTPUT(po18)
OUTPUT(po19)
OUTPUT(po20)
OUTPUT(po21)
n0 = gnd
n1 = vdd
n14 = LUT 0x1 (n2)
n15 = LUT 0x2 (n3)
n16 = LUT 0x1000 (n2, n4, n5, n6)
n17 = LUT 0x2 (n4, n7)
n18 = LUT 0x00008000 (n4, n7, n8, n9, n10)
n19 = LUT 0x00000000 (n4, n7, n8, n9, n10)
n20 = LUT 0xa2222222 (n4, n7, n8, n9, n10)
n21 = LUT 0x1 (n11)
n22 = LUT 0x8 (n11, n12)
n23 = LUT 0x02 (n4, n7, n13)
n24 = LUT 0x0000000000008000 (n4, n7, n8, n9, n10, n13)
n25 = LUT 0x0000000000000000 (n4, n7, n8, n9, n10, n13)
n26 = LUT 0x0800 (n8, n9, n10, n13)
n27 = LUT 0x0000 (n8, n9, n10, n13)
n28 = LUT 0xf000000080000000 (n4, n7, n8, n9, n10, n13)
n29 = LUT 0x08880888 (n4, n7, n8, n9, n10)
n30 = LUT 0x10 (n2, n4, n5)
n31 = LUT 0xfffffffc (n6, n18, n19, n20, n30)
n32 = LUT 0xffffffff08880888 (n4, n7, n8, n9, n10, n31)
n33 = LUT 0x0000000008880888 (n4, n7, n8, n9, n10, n13)
n34 = LUT 0x7700 (n8, n9, n10, n13)
po0 = LUT 0x2 (n14)
po1 = LUT 0x2 (n15)
po2 = LUT 0x2 (n16)
po3 = LUT 0x2 (n17)
po4 = LUT 0x2 (n18)
po5 = LUT 0x2 (n19)
po6 = LUT 0x2 (n20)
po7 = LUT 0x2 (n21)
po8 = LUT 0x2 (n22)
po9 = LUT 0x2 (n23)
po10 = LUT 0x2 (n24)
po11 = LUT 0x2 (n25)
po12 = LUT 0x2 (n26)
po13 = LUT 0x2 (n27)
po14 = LUT 0x2 (n28)
po15 = LUT 0x2 (n19)
po16 = LUT 0x2 (n29)
po17 = LUT 0x2 (n32)
po18 = LUT 0x2 (n25)
po19 = LUT 0x2 (n33)
po20 = LUT 0x2 (n27)
po21 = LUT 0x2 (n34)

As you may see, node n19 is equivalent to a constant false. Detecting and propagating this to primary output it looks not so complex. What I'm not able to manage is how to simplify node n31 receiving n19 as input. This redundancy seems to happen only in case the node is feeding a primary output.
Is there anything I can do to remove such redundancies?

The source code I use is pretty simple. Something like:

    lut_mapping_stats st;
    mapping_view<klut_network, true> mapped_aig{aig};
    lut_mapping<decltype( mapped_aig ), true>( mapped_aig, {}, &st );
    const auto klut = *collapse_mapped_network<klut_network>( mapped_aig );
   mockturtle::write_bench(klut, std::cout);

Cheers,

Fabrizio

feature request: is_po

The network interface API contains foreach_pi and foreach_po. However it has is_pi but seemingly no is_po. Looking at the implementations of is_pi, it seems like maybe this is deliberate as there isn't a way to implement it efficiently? Seems like one can roll their own as something like:

// untested
bool is_po(const aig_network &net, const node &n) {
  bool match = false;
  net.foreach_po([&](const signal &s) {
    if (node_to_index(n) == s.index) {
      match = true;
      return false;
    }
    return true;
  });
  return match;
}

Do you think this is suitable for inclusion in mockturtle?

incorrect comparison in XMG logic

When compiling with -Wparentheses GCC 9.2.0 has this to say:

In file included from /home/matthew/project/mockturtle/include/mockturtle/algorithms/node_resynthesis/xmg_npn.hpp:47:0,
                 from /home/matthew/project/mockturtle/include/mockturtle/mockturtle.hpp:71,
                 from /home/matthew/project/project/main.cc:8:
/home/matthew/project/mockturtle/include/mockturtle/algorithms/node_resynthesis/../../networks/xmg.hpp: In member function ‘mockturtle::xmg_network::signal mockturtle::xmg_network::create_maj(mockturtle::xmg_network::signal, mockturtle::xmg_network::signal, mockturtle::xmg_network::signal)’:
/home/matthew/project/mockturtle/include/mockturtle/algorithms/node_resynthesis/../../networks/xmg.hpp:300:23: warning: suggest parentheses around comparison in operand of ‘==’ [-Wparentheses]
     else if ( a.index == b.index == c.index )
               ~~~~~~~~^~~~~~~~~~

This looks to me like a legitimate problem. Is this supposed to read a.index == b.index && b.index == c.index?

Bug in refactoring

Describe the bug
Refactoring can lead to segmentation fault which is detected by the assert at line 267 in mffc_view.

This is due to the use of reference counters to keep track of the fanout of the gates. Reference counters can be invalidated after a node substitution. Moreover there are some wrong updates to the reference counters. The right way of keeping the fanout information correct is to use directly the fanout size field of gates.

To Reproduce
I haven't found a way of reproducing it using "standard'' mockturtle yet.

Environment

  • OS: Linux
  • Compiler: GCC 12.2
  • Compilation mode: DEBUG and RELEASE

Additional information
I know how to solve the bug. I will find time to fix it properly in the next weeks.
The proposed fix is to replace the use of reference counters with the fanout_size.

multiply defined xmg_dont_cares_optimization

When linking against commit 23401c1 of mockturtle, we get the following error:

...
../libfoo/libfoo.a(bar.cc.o): In function `mockturtle::xmg_dont_cares_optimization(mockturtle::xmg_network const&)':
bar.cc:(.text+0x5cb2): multiple definition of `mockturtle::xmg_dont_cares_optimization(mockturtle::xmg_network const&)'
CMakeFiles/foo.dir/main.cc.o:main.cc:(.text+0x5cb2): first defined here
../libfoo/libfoo.a(baz.cc.o): In function `mockturtle::xmg_dont_cares_optimization(mockturtle::xmg_network const&)':
baz.cc:(.text+0x5cb2): multiple definition of `mockturtle::xmg_dont_cares_optimization(mockturtle::xmg_network const&)'
CMakeFiles/foo.dir/main.cc.o:main.cc:(.text+0x5cb2): first defined here
../libfoo/libfoo.a(qux.cc.o): In function `mockturtle::xmg_dont_cares_optimization(mockturtle::xmg_network const&)':
qux.cc:(.text+0x5cb2): multiple definition of `mockturtle::xmg_dont_cares_optimization(mockturtle::xmg_network const&)'
CMakeFiles/foo.dir/main.cc.o:main.cc:(.text+0x5cb2): first defined here
collect2: error: ld returned 1 exit status

The root cause seems to be that xmg_dont_cares_optimization is a free-standing non-template non-static non-inline function in a header, so it ends up exported in multiple translation units. Is this intended to be inline?

Bus logic operations

In several of our key benchmarks (BOOM, Rocket...), we have a high percentage of cells using buses.

I mean, we do xor or and for a bus not a single bit wire. Checking BOOM, over 10% of the gates
are for buses, since they are multibit, if I flatten the number of gates more than doubles. We could "flatten" the wire to use mockturle bit representation, but it is an unnecessary overhead. Also, different bits can have slightly different (but equally good) results break symmetry.

Do you have anything on the plan to handle buses? (notice, this is not the same as nary functions that you have)

(satlut) Error in window selection.

Trying to run the satlut experiments fails for benchmarks log2, multiplier, sqrt and voter. They all fail while computing windows, more specifically at:

Assertion failed: (false), function compute_window_for, file mockturtle/include/mockturtle/algorithms/cell_window.hpp, line 150.

Which seems to be checking if the size of the pivot mffc cone is grater the a maximum defined size for windows. Maybe the intended behaviour should be to simply ignore this window this as a pivot.

ALAP in depth_view

I implemented a draft (but not complete -- consideration of inverter cost is missing, and maybe some more details, plus documentation and tests etc. are also missing) during research but didn't need it in the end, so just to keep a back-up here in case someone decides that it's useful and makes a PR in the future.

As a public member function of depth_view:

  void ALAP()
  {
    _levels.reset( 0 );
    this->incr_trav_id();

    this->foreach_po( [&]( auto const& f ) {
      const auto n = this->get_node( f );
      if ( !this->is_constant( n ) && this->visited( n ) != this->trav_id() && !this->is_pi( n ) )
      {
        _levels[n] = _depth;
        compute_levels_ALAP( n );
      }
    } );
  }

As a private member function of depth_view:

  void compute_levels_ALAP( node const& n )
  {
    this->set_visited( n, this->trav_id() );

    this->foreach_fanin( n, [&]( auto const& fi ) {
      auto const ni = this->get_node( fi );
      if ( !this->is_constant( ni ) && !this->is_pi( ni ) )
      {
        assert( _levels[n] >= _cost_fn( *this, ni ) );
        auto fi_level = _levels[n] - _cost_fn( *this, ni );
        if ( this->visited( ni ) != this->trav_id() || _levels[ni] > fi_level )
        {
          _levels[ni] = fi_level;
          compute_levels_ALAP( ni );
        }
      }
    } );
  }

Network fails equivalence check after applying the refactoring operation with direct_resynthesis twice

Hi,

I was experimenting with the refactoring operation and noticed that if I apply it twice with the direct_resynthesis resynthesis engine to the "adder" network from the EPFL Arithmetic benchmark (https://github.com/lsils/benchmarks/tree/master/arithmetic), then the resultant network is no longer equivalent to the original network. However, this is not the case if I apply the refactoring operation only once or change the resynthesis engine to exact_aig_resynthesis. Do you maybe know why this is the case?

The code below illustrates how this reproduce this issue.

#include <iostream>
#include <mockturtle/mockturtle.hpp>

using namespace std;
using namespace mockturtle;

int main() {

    string epfl_arithmetic_benchmark_dir = "/path/to/epfl/arithmetic/benchmark/";
    string ntk_name = "adder.aig";

    // load network
    aig_network ntk;
    auto const loading_res = lorina::read_aiger(epfl_arithmetic_benchmark_dir + ntk_name, aiger_reader(ntk));
    assert(loading_res == lorina::return_code::success);
    cout << "Network " << ntk_name << " has been loaded successfully" << "\n";

    // make a copy of the ntk for equivalence checking
    aig_network original_ntk = ntk;

    // refactoring parameters
    refactoring_params refactor_ps;
    refactor_ps.max_pis = 3u;
    direct_resynthesis<aig_network> refactor_resyn;

    // Apply refactoring twice
    refactoring(ntk, refactor_resyn, refactor_ps);
    ntk = cleanup_dangling(ntk);

    refactoring(ntk, refactor_resyn, refactor_ps);
    ntk = cleanup_dangling(ntk);

    // equivalence checking
    const auto miter_ntk = *miter<aig_network>(original_ntk, ntk);
    const auto equivalence_res = equivalence_checking(miter_ntk);

    /* result is an optional, which is nullopt if no solution was found */
    if (equivalence_res && *equivalence_res) {
        cout << "networks are equivalent after applying sequence\n";
    }
    else{
        cout << "networks are NOT equivalent after applying sequence\n";
    }
}

adder.zip

multiple definition

When I use mockturtle as a library in my project, I meet a problem about "multiple definition", can you help me?

../aqfp/libscflow.a(MajOpt.cpp.o): In function `mockturtle::generate_aqfp_dags(mockturtle::dag_generator_params const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)':
~/SCFlow/third-party/mockturtle/include/mockturtle/algorithms/aqfp_resynthesis/detail/db_utils.hpp:51: multiple definition of `mockturtle::generate_aqfp_dags(mockturtle::dag_generator_params const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)'
../aqfp/libscflow.a(Synthesis.cpp.o):~/SCFlow/third-party/mockturtle/include/mockturtle/algorithms/aqfp_resynthesis/detail/db_utils.hpp:51: first defined here
../aqfp/libscflow.a(MajOpt.cpp.o): In function `mockturtle::compute_aqfp_dag_costs(std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)':
~/SCFlow/third-party/mockturtle/include/mockturtle/algorithms/aqfp_resynthesis/detail/db_utils.hpp:95: multiple definition of `mockturtle::compute_aqfp_dag_costs(std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)'
../aqfp/libscflow.a(Synthesis.cpp.o):~/SCFlow/third-party/mockturtle/include/mockturtle/algorithms/aqfp_resynthesis/detail/db_utils.hpp:95: first defined here
../aqfp/libscflow.a(MajOpt.cpp.o): In function `mockturtle::generate_aqfp_db(std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)':
~/SCFlow/third-party/mockturtle/include/mockturtle/algorithms/aqfp_resynthesis/detail/db_utils.hpp:155: multiple definition of `mockturtle::generate_aqfp_db(std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)'
../aqfp/libscflow.a(Synthesis.cpp.o):~/SCFlow/third-party/mockturtle/include/mockturtle/algorithms/aqfp_resynthesis/detail/db_utils.hpp:155: first defined here
../aqfp/libscflow.a(MajOpt.cpp.o): In function `mockturtle::generate_aqfp_db(mockturtle::dag_generator_params const&, std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)':
~/SCFlow/third-party/mockturtle/include/mockturtle/algorithms/aqfp_resynthesis/detail/db_utils.hpp:264: multiple definition of `mockturtle::generate_aqfp_db(mockturtle::dag_generator_params const&, std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::unordered_map<unsigned int, double, std::hash<unsigned int>, std::equal_to<unsigned int>, std::allocator<std::pair<unsigned int const, double> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)'
../aqfp/libscflow.a(Synthesis.cpp.o):~/SCFlow/third-party/mockturtle/include/mockturtle/algorithms/aqfp_resynthesis/detail/db_utils.hpp:264: first defined here
../aqfp/libscflow.a(MajOpt.cpp.o): In function `mockturtle::self_dualize_aig(mockturtle::aig_network const&)':
~/SCFlow/third-party/mockturtle/include/mockturtle/generators/self_dualize.hpp:57: multiple definition of `mockturtle::self_dualize_aig(mockturtle::aig_network const&)'
../aqfp/libscflow.a(Synthesis.cpp.o):~/SCFlow/third-party/mockturtle/include/mockturtle/generators/self_dualize.hpp:57: first defined here
collect2: error: ld returned 1 exit status

Using mockturtle as a library in another project

I've seen the documentation and I did add the include directory of mockturtule to my include directory but just simply including mock turtule by #include <mockturtle/mockturtle.hpp> doesn't work because of the source code dependency on other library like "lorina".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.