2017-06-28 19:06:26 +02:00
|
|
|
\documentclass[11pt,a4paper]{article}
|
|
|
|
\usepackage[utf8]{inputenc}
|
|
|
|
\usepackage[T1]{fontenc}
|
|
|
|
\usepackage{amsmath}
|
|
|
|
\usepackage{amsfonts}
|
|
|
|
\usepackage{amssymb}
|
|
|
|
\usepackage{graphicx}
|
|
|
|
\usepackage{indentfirst}
|
|
|
|
\usepackage{enumerate}
|
|
|
|
\usepackage{caption}
|
2017-08-20 14:05:12 +02:00
|
|
|
\usepackage{algorithmicx}
|
2017-08-19 12:30:11 +02:00
|
|
|
\usepackage[backend=biber,style=trad-alpha]{biblatex}
|
2017-06-28 19:06:26 +02:00
|
|
|
\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
|
|
|
|
|
|
|
|
|
|
|
|
% Custom packages
|
|
|
|
\usepackage{todo}
|
|
|
|
\usepackage{leftrule_theorems}
|
|
|
|
\usepackage{my_listings}
|
|
|
|
\usepackage{my_hyperref}
|
2017-08-19 16:35:11 +02:00
|
|
|
\usepackage{../common/internship}
|
2017-08-19 18:03:20 +02:00
|
|
|
\usepackage{../common/math}
|
2017-06-28 19:06:26 +02:00
|
|
|
|
2017-08-19 12:30:11 +02:00
|
|
|
\bibliography{../common/refs}
|
|
|
|
|
2017-06-28 19:40:32 +02:00
|
|
|
\title{Pattern-matching and substitution in electronic circuits}
|
2017-08-19 12:30:11 +02:00
|
|
|
\author{Théophile Bastian, under supervision of Carl-Johan Seger
|
|
|
|
and Mary Sheeran\\
|
2017-06-28 19:40:32 +02:00
|
|
|
\small{Chalmers University, Göteborg, Sweden}}
|
|
|
|
\date{February~--~June 2017}
|
2017-06-28 19:06:26 +02:00
|
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|
|
|
|
\begin{document}
|
|
|
|
\maketitle
|
|
|
|
|
|
|
|
\begin{abstract}
|
2017-08-19 20:41:46 +02:00
|
|
|
\todo{enhance abstract?}
|
|
|
|
|
|
|
|
The present report describes and summarizes my 1st year of Master's
|
|
|
|
degree's internship at the university of Chalmers, Göteborg, Sweden. I
|
|
|
|
worked under supervision of Carl-Johan Seger and Mary Sheeran.
|
|
|
|
|
|
|
|
The project's goal was to contribute to VossII, a hardware proving tool
|
|
|
|
cloning fl, developed at Intel by Carl Seger for internal usage only. It
|
|
|
|
led me to work on \emph{pattern-matching} on electronic circuits for a
|
|
|
|
\emph{search-and-replace} method, allowing one to apply previously proved
|
|
|
|
transformations to a circuit.
|
|
|
|
|
|
|
|
This problem turns out to be more or less the \emph{subgraph isomorphism
|
|
|
|
problem}, which is NP-complete, and must nevertheless be solved fast on
|
|
|
|
processor-sized circuits on this particular case.
|
|
|
|
|
|
|
|
During my internship, I developed a C++ library to perform this task that
|
|
|
|
will be integrated in VossII, based on a few well-known algorithms as well
|
|
|
|
as some ad-hoc heuristics and algorithm tweaks to better match the context
|
|
|
|
of circuits. One of my objectives all along was also to keep a clean and
|
|
|
|
well-documented codebase, as the tool will have to be maintainable by
|
|
|
|
others later.
|
2017-06-28 19:06:26 +02:00
|
|
|
\end{abstract}
|
|
|
|
|
|
|
|
\tableofcontents
|
|
|
|
|
2017-08-20 14:05:12 +02:00
|
|
|
\todo{Talk of the repo, somewhere}
|
|
|
|
|
2017-06-28 19:40:32 +02:00
|
|
|
\pagebreak
|
|
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
\section{Introduction}
|
|
|
|
|
2017-08-19 10:56:04 +02:00
|
|
|
In the previous years, verification and proved software has gathered an
|
|
|
|
increasing interest in the computer science community, as people realised how
|
|
|
|
hard bugs are to track down. But hardware bugs are even more tedious to find
|
|
|
|
and fix, and can easily lead to disastrous consequences, as those cannot be
|
|
|
|
patched on existing hardware. For instance, the well-known Pentium
|
2017-08-19 12:30:11 +02:00
|
|
|
``\textsc{fdiv}'' bug~\cite{pratt1995fdiv} that affected a large number of
|
2017-08-19 10:56:04 +02:00
|
|
|
Pentium processors lead to wrong results for some floating point divisions.
|
2017-08-19 16:35:11 +02:00
|
|
|
Intel had to offer to replace all the defective CPUs, leading to an announced
|
|
|
|
loss of 475 million dollars~\cite{nicely_fdiv}. Even recently, the Skylake and
|
|
|
|
Kaby Lake hyperthreading bug had to be patched using microcode, loosing
|
|
|
|
performance and reliability.
|
2017-08-19 10:56:04 +02:00
|
|
|
|
|
|
|
To avoid such disasters, the industry nowadays uses a wide range of techniques
|
2017-08-19 16:35:11 +02:00
|
|
|
to catch bugs as early as possible --- which, hopefully, is before the product's
|
2017-08-19 10:56:04 +02:00
|
|
|
release date. Among those are \todo{list + cite}, but also proved hardware. On
|
|
|
|
circuits as complex as processors, usually, only sub-components are proved
|
2017-08-19 16:35:11 +02:00
|
|
|
correct in a specified context --- that should, but is not proved to, be
|
2017-08-19 10:56:04 +02:00
|
|
|
respected by the other parts of the circuit. Yet, this trade-off between proved
|
|
|
|
correctness and engineer's work time already gives a pretty good confidence in
|
|
|
|
the circuit.
|
|
|
|
|
2017-08-19 16:35:11 +02:00
|
|
|
In this context, Carl Seger was one of the main developers of fl at Intel, a
|
|
|
|
functional ml-inspired programming language integrating many features useful to
|
|
|
|
get insights of a circuit, testing it and proving it. It mostly features
|
|
|
|
symbolic trajectory evaluation based model checking and theorem proving, and is
|
|
|
|
intended to be an all-purpose toolbox for the hardware prover.
|
|
|
|
|
2017-08-19 10:56:04 +02:00
|
|
|
Among other features, it includes a ``search and replace'' feature, which can
|
|
|
|
search every occurrence of a given gates pattern in a circuit, and replace it
|
2017-08-19 16:35:11 +02:00
|
|
|
by some other gates pattern, proved observationally equivalent beforehand.
|
2017-08-19 10:56:04 +02:00
|
|
|
Time has proved this method very efficient to design circuits: this way, one
|
|
|
|
can start from an inefficient, yet simple circuit, prove it, and then refine it
|
|
|
|
into an equivalent, yet efficient one, through proved transformations. It is
|
|
|
|
also possible to go the other way, and start with an optimized circuit, hard to
|
|
|
|
understand, and make it easier to understand to work more efficiently.
|
|
|
|
|
2017-08-19 16:35:11 +02:00
|
|
|
\paragraph{My internship} lies amid a project shared between Carl-Johan Seger
|
|
|
|
and Mary Sheeran, aiming to develop tools for proved design of FPGA circuits.
|
|
|
|
One of the keystones of this project is an open-sourced and publicly available
|
|
|
|
version of fl, used for the proving part, and is still at the moment under
|
|
|
|
development.
|
|
|
|
|
|
|
|
My part of the work resided on this ``search and replace'' tool. More
|
|
|
|
specifically, I focused on writing a C++ library, \emph{isomatch}, which is
|
|
|
|
interfaced with the C core of fl and provides it with low-level and very fast
|
|
|
|
functions for this task.
|
|
|
|
|
2017-08-19 10:56:04 +02:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
2017-08-19 19:30:25 +02:00
|
|
|
\section{Problem setting}
|
2017-08-19 16:35:11 +02:00
|
|
|
|
2017-08-19 18:03:20 +02:00
|
|
|
\subsection{Circuit description}
|
|
|
|
|
2017-08-19 16:35:11 +02:00
|
|
|
\begin{figure}[!h]
|
|
|
|
\begin{align*}
|
2017-08-19 18:03:20 +02:00
|
|
|
\textbf{Integer constant } n, m, p, q, \ldots \qquad& \\
|
2017-08-19 16:35:11 +02:00
|
|
|
\\
|
|
|
|
\textbf{Wire } in0, out0, ctl0, \ldots \qquad& \\
|
|
|
|
\\
|
|
|
|
\textbf{Vector } \evec{v}{n} & & \textit{($n$ elements of type $v$)} \\
|
|
|
|
\\
|
|
|
|
\textbf{Circuit } c, d, \ldots ::=~
|
|
|
|
&\text{delay} (in0, out0) &\textit{(delay 1 clock tick)} \\
|
|
|
|
\vert~&\text{tristate} (in0, out0, ctl0)
|
|
|
|
&\textit{(three-state gate)} \\
|
|
|
|
\vert~&\text{comb} (\evec{in0}{n}, \evec{out0}{m}, \evec{e}{m})
|
|
|
|
&\textit{(combinatorial gate)} \\
|
2017-08-19 18:03:20 +02:00
|
|
|
\vert~&\text{assert} (\evec{in0}{n}, \evec{e}{m})
|
2017-08-19 16:35:11 +02:00
|
|
|
&\textit{(assertion gate)} \\
|
2017-08-19 18:03:20 +02:00
|
|
|
\vert~&\text{group} (\evec{in0}{n}, \evec{out0}{m}, \evec{c}{p})
|
2017-08-19 16:35:11 +02:00
|
|
|
&\textit{(circuit hierarchical group)} \\
|
|
|
|
\\
|
|
|
|
\textbf{Binary operator } \otimes ::=~
|
|
|
|
&\wedge & \textit{(and)} \\
|
|
|
|
\vert~&\vee & \textit{(or)} \\
|
|
|
|
\vert~&\oplus & \textit{(xor)} \\
|
|
|
|
\vert~&+ & \textit{(add)} \\
|
|
|
|
\vert~&- & \textit{(sub)} \\
|
|
|
|
\vert~&\times & \textit{(times)} \\
|
|
|
|
\vert~&\div & \textit{(div)} \\
|
|
|
|
\vert~&\% & \textit{(mod)} \\
|
|
|
|
\vert~&\lsl & \textit{(logical shift left)} \\
|
|
|
|
\vert~&\lsr & \textit{(logical shift right)} \\
|
|
|
|
\vert~&\asr & \textit{(arithmetic shift right)} \\
|
|
|
|
\\
|
|
|
|
\textbf{Unary and constant operator } \otimes_0 ::=~
|
|
|
|
&\clsl & \textit{(logical shift left of constant)} \\
|
|
|
|
\vert~&\clsr & \textit{(logical shift right of constant)} \\
|
|
|
|
\vert~&\casr & \textit{(arithmetic shift right of constant)} \\
|
|
|
|
\\
|
|
|
|
\textbf{Unary operator } \ominus ::=~
|
|
|
|
&\lnot & \textit{(logical negation)} \\
|
|
|
|
\\
|
|
|
|
\textbf{Expression } e, f, \ldots ::=~
|
|
|
|
& x & \textit{(variable)} \\
|
|
|
|
\vert~& n & \textit{(integer constant)} \\
|
|
|
|
\vert~& e \otimes f & \textit{(binary operator)} \\
|
|
|
|
\vert~& e \otimes_0 n & \textit{(unary operator with constant)} \\
|
|
|
|
\vert~& \ominus e & \textit{(unary operator)} \\
|
|
|
|
\vert~& e_{\vert~n \ldots m} & \textit{(slicing: take a subword)}\\
|
|
|
|
\vert~& e~\vert~f & \textit{(merging: concatenate two words)} \\
|
|
|
|
\end{align*}
|
|
|
|
\caption{AST of circuits used}\label{fig:ast}
|
|
|
|
\end{figure}
|
2017-06-28 19:40:32 +02:00
|
|
|
|
2017-08-19 18:03:20 +02:00
|
|
|
The circuits on which \emph{isomatch} is working are described, and internally
|
|
|
|
represented, by the AST in Figure~\ref{fig:ast}.
|
|
|
|
|
|
|
|
The most important thing in the description of circuits here, is that those
|
|
|
|
circuits are organized as a hierarchy of \emph{circuit groups}. This hierarchy
|
|
|
|
can be seen as the construction of a circuit by assembling smaller integrated
|
|
|
|
circuits (ICs), themselves built the same way, etc. A group is composed of
|
|
|
|
sub-circuits, input pins and output pins. Each level can of course contain
|
|
|
|
``leaf'' gates, like \textit{and} or \textit{delay} gates. This is important,
|
|
|
|
because it allows the program to work on smaller areas the circuit (\eg{}
|
|
|
|
loading in memory only a part of the circuit, etc.).
|
|
|
|
|
2017-08-19 19:30:25 +02:00
|
|
|
\subsection{Objective}
|
2017-08-19 12:30:11 +02:00
|
|
|
|
2017-08-19 18:03:20 +02:00
|
|
|
More precisely, the problems that \emph{isomatch} must solve are the following.
|
|
|
|
|
|
|
|
\begin{enumerate}
|
|
|
|
\item\label{prob:equal} Given two circuit groups, are they structurally
|
|
|
|
equivalent? That is, are they the same circuit, arranged in a different
|
|
|
|
way, with possibly different names, etc.?
|
|
|
|
|
|
|
|
\item\label{prob:match} Given two circuits, \emph{needle} and
|
|
|
|
\emph{haystack}, find every (non-overlapping) occurrence of \emph{needle} in
|
|
|
|
\emph{haystack}. An occurrence is a set $S$ of sub-circuits of
|
|
|
|
\emph{haystack} such that there is a one-to-one mapping of structurally
|
|
|
|
equivalent circuits of $S$ with circuits of \emph{needle}, and those
|
|
|
|
circuits are connected the same way in both circuits.
|
|
|
|
\end{enumerate}
|
|
|
|
|
|
|
|
Both problems are hard. The first one is an instance of graph isomorphism, as
|
|
|
|
the actual question is whether there exists a one-to-one mapping between
|
|
|
|
sub-circuits of the two groups, such that every mapped circuit is equal to the
|
|
|
|
other (either directly if it is a leaf gate, or recursively with the same
|
|
|
|
procedure); and whether this mapping respects connections (edges) between those
|
|
|
|
circuits. Graph isomorphism is known to be in NP (given a permutation of the
|
|
|
|
first graph, it is polynomial to check whether the first is equal to the second
|
|
|
|
\wrt{} the permutation), but not known to be in either P or NP-complete. Thus,
|
|
|
|
since Babai's work on graph isomorphism~\cite{babai2016graph} is only of
|
|
|
|
theoretical interest, the known algorithms remain in worst-case exponential
|
|
|
|
time, and require ad-hoc heuristics for specific kind of graphs to get maximum
|
|
|
|
efficiency.
|
|
|
|
|
|
|
|
The second one is an instance of subgraph isomorphism problem, which is known
|
|
|
|
to be NP-complete~\cite{cook1971complexity}. Even though a few algorithms
|
|
|
|
(discussed later) are known to be efficient in most cases for this problem, it
|
|
|
|
is nevertheless necessary to implement them the right way, and with the right
|
|
|
|
heuristics, to get the desired efficiency for the given problem.
|
2017-06-28 19:40:32 +02:00
|
|
|
|
2017-08-19 19:30:25 +02:00
|
|
|
\subsection{Sought efficiency}
|
|
|
|
|
|
|
|
The goal of \textit{isomatch} is to be applied to large circuits on-the-fly,
|
|
|
|
during their conception. Those circuits can (and will probably) be as large as
|
|
|
|
a full processor, and the software will be operated by a human, working on
|
|
|
|
their circuit. Thus, \textit{isomatch} must be as fast as possible, since
|
|
|
|
matching operation will be executed often, and often multiple times in a row.
|
|
|
|
It must then remain fast enough for the human not to lose too much time, and
|
|
|
|
eventually lose patience.
|
|
|
|
|
2017-08-19 23:25:21 +02:00
|
|
|
\todo{Mention clean codebase somewhere}
|
|
|
|
|
|
|
|
\todo{Mention VossII somewhere}
|
|
|
|
|
2017-08-19 19:30:25 +02:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
\section{General approach}
|
|
|
|
|
2017-08-19 23:25:21 +02:00
|
|
|
The global strategy used to solve efficiently the problem can be broken down to
|
|
|
|
three main parts.
|
|
|
|
|
|
|
|
\paragraph{Signatures.} The initial idea to make the computation fast is to
|
|
|
|
aggregate the inner data of a gate --- be it a leaf gate or a group --- in a
|
2017-08-20 14:05:12 +02:00
|
|
|
kind of hash, a 64 bits unsigned integer. This approach is directly inspired
|
2017-08-19 23:25:21 +02:00
|
|
|
from what was done in fl, back at Intel. This hash must be easy to compute,
|
|
|
|
and must be based only on the structure of the graph --- that is, must be
|
|
|
|
entirely oblivious of the labels given, the order in which the circuit is
|
|
|
|
described, the order in which different circuits are plugged on a wire, \ldots.
|
|
|
|
The signature equality, moreover, must be sound; that is, two signatures must
|
|
|
|
necessarily be equal if the circuits are indeed equal.
|
|
|
|
|
|
|
|
This makes it possible to rule out quickly whether two circuits are candidates
|
|
|
|
for a match or not, and run the costy actual equality algorithm on fewer gates.
|
|
|
|
|
|
|
|
|
|
|
|
\paragraph{Group equality.} The group equality algorithm is a standard
|
|
|
|
backtracking algorithm. It tries to build a match between the graphs by
|
|
|
|
trying the diverse permutations of elements with the same signature. It can
|
|
|
|
also communicate with the signing part, to request a more precise (but slightly
|
|
|
|
slower to compute) signature when it has too many permutations to try.
|
|
|
|
|
|
|
|
This part could be enhanced, but does not slow down the algorithm on the tested
|
|
|
|
examples, so I focused on other parts.
|
|
|
|
|
|
|
|
|
|
|
|
\paragraph{Pattern matching.} This part is the one responsible to answer
|
|
|
|
queries for occurrences of a sub-circuit in a circuit. It uses extensively the
|
|
|
|
signatures to determine whether two circuits could be a match or not before
|
|
|
|
spending too much time actually finding matches, but cannot rely on it as
|
|
|
|
heavily as group equality, since only the first level of precision is
|
|
|
|
applicable here (detailed later).
|
|
|
|
|
|
|
|
This part mostly consists in an implementation of Ullmann's algorithm for
|
|
|
|
subgraph isomorphism~\cite{ullmann1976algorithm}, a well-known algorithm for
|
|
|
|
this problem, that uses the specificities of the graph to be a little faster.
|
|
|
|
|
2017-06-28 19:40:32 +02:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
\section{Signatures}
|
2017-08-20 14:05:12 +02:00
|
|
|
|
|
|
|
The signature is computed as a simple hash of the element, and is defined for
|
|
|
|
every type of expression and circuit. It could probably be enhanced with a bit
|
|
|
|
more work to cover more uniformly the hash space, but no collision was observed
|
|
|
|
on the examples tested.
|
|
|
|
|
|
|
|
\paragraph{Signature constants.} Signature constants are used all around the
|
|
|
|
signing process, and is a 5-tuple $\sigconst{} = (a, x_l, x_h, d_l, d_h)$ of 32
|
|
|
|
bits unsigned numbers. All of $x_l$, $x_h$, $d_l$ and $d_h$ are picked as prime
|
|
|
|
numbers between $10^8$ and $10^9$ (which just fits in a 32 bits unsigned
|
|
|
|
integer); while $a$ is a random integer uniformly picked between $2^{16}$ and
|
|
|
|
$2^{32}$. These constants are generated by a small python script,
|
|
|
|
\path{util/primegen/pickPrimes.py}.
|
|
|
|
|
|
|
|
Those constants are used to produce a 64 bits unsigned value out of another 64
|
|
|
|
bits unsigned value, called $v$ thereafter, through an operator $\sigop$,
|
2017-08-20 16:39:23 +02:00
|
|
|
computed as follows (with all computations done on 64 bits unsigned integers).
|
2017-08-20 14:05:12 +02:00
|
|
|
|
2017-08-20 16:39:23 +02:00
|
|
|
\vspace{1em}
|
2017-08-20 14:05:12 +02:00
|
|
|
\begin{algorithmic}
|
|
|
|
\Function{$\sigop$}{$\sigconst{}, v$}
|
|
|
|
\State{} $out1 \gets (v + a) \cdot x_l$
|
|
|
|
\State{} $v_h \gets (v \lsr 32) \xor (out1 \lsr 32)$
|
|
|
|
\State{} $low \gets out1 \,\%\, d_l$
|
|
|
|
\State{} $high \gets \left((v_h + a) \cdot x_h \right) \%\, d_h$
|
|
|
|
\State{} \Return{} $low + 2^{32} \cdot high$
|
|
|
|
\EndFunction{}
|
|
|
|
\end{algorithmic}
|
2017-06-28 19:40:32 +02:00
|
|
|
|
2017-08-20 16:39:23 +02:00
|
|
|
\paragraph{Expressions.} Each type of expression (or, in the case of
|
|
|
|
expression with operator, each type of operator) has its signature constant,
|
|
|
|
$\sigconst{\text{exprType}}$. The signature of a commutative expression in its
|
|
|
|
operands is always commutative, and the signature of a non-commutative
|
|
|
|
expression should not be (and is not, except for collisions). The value $v$
|
|
|
|
used to sign the expression (in $\sigop(\sigconst{\text{exprType}}, v)$) is
|
|
|
|
then the sum (respectively difference) of the signature of its parameters for
|
|
|
|
commutative (respectively non-commutative) expressions.
|
|
|
|
|
|
|
|
\paragraph{Circuits' inner signature.} Every circuit is associated with a value
|
|
|
|
describing its \emph{type} (rather than its contents): 8 bits of circuit type
|
|
|
|
ID (delay, tristate, \ldots), the number of inputs on the next 8 bits, and the
|
|
|
|
number of outputs on 8 more bits. This value is then xored with the inner value
|
|
|
|
of the circuit: for a combinatorial gate, the xor of its expressions'
|
|
|
|
signatures; for a group, the sum of its children's signatures\footnote{As a
|
|
|
|
group is likely to have multiple occurrences of a single identical circuit, it
|
|
|
|
would be unwise to xor its children's signatures, even though the usual advice
|
|
|
|
is to combine hashes by xoring them.}, \ldots This value constitutes the
|
|
|
|
circuit's \emph{inner signature}.
|
|
|
|
|
|
|
|
\paragraph{Circuits' signature of order $n$.} The inner signature does not
|
|
|
|
capture at all the \emph{structure} of the graph. An information we can capture
|
|
|
|
without breaking the signature's independence towards the order of description
|
|
|
|
of the graph, is the set of its neighbours. Yet, we cannot ``label'' the gates
|
|
|
|
without breaking this rule; thus, we represent the set of neighbours by the set
|
|
|
|
of our \emph{neighbours' signatures}.
|
|
|
|
|
|
|
|
At this point, we can define the \emph{signature of order $n$} ($n \in
|
|
|
|
\natset$) of a circuit $C$ as follows:
|
|
|
|
|
|
|
|
\begin{align*}
|
|
|
|
\sig_0(C) :&= \text{inner signature of } C\\
|
|
|
|
\sig_{n+1}(C) :&= \text{inner signature of }C
|
|
|
|
+ \text{IO adjacency}
|
|
|
|
+ \hspace{-2em}\sum\limits_{C_i \in \,\text{neighbours of inputs}}
|
|
|
|
\hspace{-2em}\sig_n(C_i) \hspace{1em}
|
|
|
|
- \hspace{-2em}\sum\limits_{C_o \in \,\text{neighbours of inputs}}
|
|
|
|
\hspace{-2em}\sig_n(C_o)
|
|
|
|
\end{align*}
|
|
|
|
|
|
|
|
The ``IO adjacency'' term is an additional term in the signatures of order
|
|
|
|
above $0$, indicating what input and output pins of the circuit group
|
|
|
|
containing the current gate are adjacent to it.
|
|
|
|
|
2017-08-20 18:00:45 +02:00
|
|
|
The default order of signature used in all computations, unless more is useful,
|
|
|
|
is 2, after a few benchmarks.
|
|
|
|
|
|
|
|
\todo{explain range of $n$}
|
|
|
|
|
2017-08-20 16:55:13 +02:00
|
|
|
\paragraph{Efficiency.} Every circuit memoizes all it can concerning its
|
|
|
|
signature: the inner signature, the IO adjacency, the signatures of order $n$
|
|
|
|
already computed, etc.
|
|
|
|
|
|
|
|
This memoization, alongside with the exclusive use of elementary operations,
|
|
|
|
makes the computation of a signature very fast. The computation is linear in
|
|
|
|
the number of gates in a circuit, times the order computed; the computation is
|
|
|
|
lazy.
|
|
|
|
|
|
|
|
To keep those memoized values up to date whenever the structure of the circuit
|
|
|
|
is changed (since this is meant to be integrated in a programming language, fl,
|
|
|
|
meaning the structure of the circuit will possibly be created, checked for
|
|
|
|
signature, altered, then checked again), each circuit keeps track of a
|
|
|
|
``timestamp'' of last modification, which is incremented whenever the circuit
|
|
|
|
or its children are modified. A memoized data is always stored alongside with a
|
|
|
|
timestamp of computation, which invalidates a previous result when needed.
|
|
|
|
|
|
|
|
One possible path of investigation for future work, if the computation turns
|
|
|
|
out to be still too slow in real-world cases --- which looks unlikely ---,
|
|
|
|
would be to try to multithread this computation.
|
|
|
|
|
2017-06-28 19:40:32 +02:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
\section{Group equality}
|
2017-08-20 18:00:45 +02:00
|
|
|
|
|
|
|
Given two circuit group gates, the task of group equality is to determine
|
|
|
|
whether the two groups are structurally equivalent, as discussed above.
|
|
|
|
|
|
|
|
Group equality itself is handled as a simple backtracking algorithm, trying to
|
|
|
|
establish a match (an isomorphism, that is, a permutation of the gates of one
|
|
|
|
of the groups) between the two groups given.
|
|
|
|
|
|
|
|
The gates of the two groups are matched by equal signatures, equal number of
|
|
|
|
inputs and outputs, based on the signature of default order (that is, 2). A few
|
|
|
|
checks are made, \eg{} every matching group must have the same size on both
|
|
|
|
sides (if not, then, necessary, the two groups won't match). Then, the worst
|
|
|
|
case of number of permutations to check is evaluated.
|
|
|
|
|
|
|
|
If this number is too high, the signature order will be incremented, and the
|
|
|
|
matching groups re-created accordingly, until a satisfyingly low number of
|
|
|
|
permutations is reached (or the diameter of the circuit is reached, meaning
|
|
|
|
that increasing the order of signature won't have any additional impact). This
|
|
|
|
order increase ``on-demand'' proved itself very efficient, effectively lowering
|
|
|
|
the number of permutations examined to no more than $4$ in studied cases.
|
|
|
|
|
|
|
|
Once a permutation is judged worth to be examined, the group equality is run
|
|
|
|
recursively on all its matched gates. If this step succeeds, the graph
|
|
|
|
structure is then checked. If both steps succeeds, the permutation is correct
|
|
|
|
and an isomorphism has been found; if not, we move on to the next permutation.
|
|
|
|
|
|
|
|
\todo{Anything more to tell here?}
|
2017-06-28 19:40:32 +02:00
|
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
\section{Pattern-match}
|
2017-08-20 18:20:20 +02:00
|
|
|
|
2017-06-28 19:40:32 +02:00
|
|
|
\todo{}
|
|
|
|
|
2017-08-20 18:20:20 +02:00
|
|
|
\subsection{Ullmann's algorithm}
|
|
|
|
|
|
|
|
One of the classical algorithms to deal with the subgraph isomorphism problem
|
|
|
|
was first described by Julian R Ullmann in 1976~\cite{ullmann1976algorithm}.
|
|
|
|
Another, more recent algorithm to deal with this problem is Luigi P Cordella's
|
|
|
|
VF2 algorithm~\cite{cordella2004sub}, published in 2004. This algorithm is
|
|
|
|
mostly Ullmann's algorithm, transcribed in a recursive writing, with the
|
|
|
|
addition of five heuristics. \qtodo{Why not use it then?}
|
|
|
|
|
|
|
|
\todo{Describe Ullmann}
|
|
|
|
|
2017-06-28 19:06:26 +02:00
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
2017-06-28 19:40:32 +02:00
|
|
|
\section{Performance}
|
2017-08-20 18:00:45 +02:00
|
|
|
|
|
|
|
\todo{}
|
|
|
|
|
|
|
|
\subsection{Corner cases}
|
|
|
|
|
2017-06-28 19:40:32 +02:00
|
|
|
\todo{}
|
2017-06-28 19:06:26 +02:00
|
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
|
2017-08-19 12:30:11 +02:00
|
|
|
\printbibliography{}
|
2017-06-28 19:06:26 +02:00
|
|
|
|
|
|
|
\end{document}
|