************************************************************************** * * * The SubCircuit C++11 library * * * * An implementation of a modified Ullmann Subgraph Isomorphism Algorithm * * for coarse grain logic networks. by Clifford Wolf * * * ************************************************************************** ============ Introduction ============ This is a library that implements a modified Ullmann Subgraph Isomorphism Algorithm with additional features aimed at working with coarse grain logic networks. It also contains a simple frequent subcircuit mining algorithm. A simple command line tool that exposes the features of the library is also included. C++11 Warning ------------- This project is written in C++11. Use appropriate compiler switches to compile it. Tested with clang version 3.0 and option -std=c++11. Also tested with gcc version 4.6.3 and option -std=c++0x. ======== Features ======== The input is two graphs (needle and haystack) that represent coarse grain logic networks. The algorithm identifies all subgraphs of haystack that are isomorphic to needle. The following additional features over the regular Ullmann Subgraph Isomorphism Algorithm are provided by the library. * The graphs are attributed hypergraphs capable of representing netlists: - Nodes represent the logic cells: - Nodes have types and only match compatible types - Nodes have ports with variable bit-width - Hyperedges represent the signals: - Each hyperedge connects one to many bits on ports on nodes - Callback functions for advanced attributes and compatibility rules: Any set of node-node compatibility rules and edge-edge compatibility rules can be implemented by providing the necessary callback functions. * The algorithm is very efficient when all or many bits of one port are connected to bits of the same other port. This is usually the case in coarse grain logic networks. But the algorithm does not add any restrictions in this area; it is just optimized for this scenario. * The algorithm can be configured to allow larger ports in needle cells to match smaller ports in haystack cells in certain situations. This way it is possible to e.g. have a 32-bit adder cell in the needle match a 16-bit adder cell in the haystack. * The algorithm can be configured to perform port-swapping on certain ports on certain cell types to match commutative operations properly. This is, however, not implemented very efficiently when a larger number of permutations is possible on a cell type. Therefore it is recommended to only use swap groups with only a few members and a few such groups on one cell type type. Also note, that the algorithm can not resolve complex dependencies between the port swappings of different cells. Therefore it is recommended to only use port swapping on input pins of commutative operations, where such complex dependencies can not emerge. * The algorithm can be configured to distinguish between internal signals of the needle and externally visible signals. The needle will only match a subgraph of the haystack if that subgraph does not expose the internal signal to nodes in the haystack outside the matching subgraph. * The algorithm can recognize a subcircuit even if some or all of its inputs and/or outputs are shorted together. * Explicit fast support for constant signals without extra nodes for constant drivers. * Support for finding only non-overlapping matches. * A simple miner for frequent subcircuts that operates on the same circuit description format. * The public API of the library is using std::string identifiers for nodes, node types and ports. Internally the costly part of the algorithm is only using integer values, thus speeding up the algorithm without exposing complex internal encodings to the caller. ================= API Documentation ================= This section gives a brief overview of the API. For a working example, have a look at the demo.cc example program in this directory. Setting up graphs ----------------- Instantiate the SubCircuit::Graph class and use the methods of this class to set up the circuit. SubCircuit::Graph myGraph; For each node in the circuit call the createNode() method. Specify the identifier for the node and also the type of function implemented by the node. Then call createPort() for each port of this node. E.g. the following code adds a node "myAdder" of type "add" with three 32 bit wide ports "A", "B" and "Y". Note that SubCircuit does not care which port is an input and which port is an output. The last (and optional) argument to createPort() specifies th