Package: circuitry
Embedded domain-specific combinator library for the abstract assembly and automated synthesis of logical circuits.PurposeThis embedded domain-specific language (DSL) makes it possible to write an algorithm in Python that operates on bit values and/or bit vectors, and then to interpret that algorithm implementation as a circuit definition in order to synthesize automatically a logical circuit represented using thecircuitlibrary. Additional background information and examples can be found in arelevant report.Installation and UsageThis library is available as apackage on PyPI:python -m pip install circuitryThe library can be imported in the usual ways:import circuitry
from circuitry import *ExamplesThis library makes it possible to embed within Python a function that operates on individual bits and/or bit vectors (subject to specific limitations) and then to automatically synthesize a logical circuit that implements that function. In the simple example below, the defined bit equality function takes twobitobjects as its inputs and returns onebitobject as its output. Because nearly all built-in Python operators are supported by thebitclass viaappropriate method definitions(e.g., see the__or__method), the statements and expressions in the function can employ a straightforward and familiar syntax:>>> from circuitry import *
>>> @synthesize
... def equal(x: bit, y: bit) -> bit:
...     return (x & y) | ((1 - x) & (1 - y))The function itself can be invoked in the usual manner if the supplied inputs are integers or instances of thebitclass:>>> equal(0, 1)
0
>>> b = equal(bit(0), bit(1))
>>> isinstance(b, bit)
True
>>> int(b)
0Thesynthesizedecorator automatically synthesizes the corresponding circuit (as an instance of thecircuitclass defined in thecircuitlibrary). The synthesizedcircuitobject is stored within an attribute of the function itself and can be evaluated on two bit values (as specified by the function’s type annotation). See the documentation of thecircuitlibrary for more information on how input bit vectors should be structured when evaluating a circuit:>>> equal.circuit.evaluate([[0], [1]])
[[0]]Thesynthesizedecorator can also be applied to functions that are defined explicitly as operating onbit vectors(where bit vectors can be represented as lists of integers or asbitsobjects). Furthermore, functions can be invoked in other functions, making it possible to reuse modular algorithm components. In the example below, the bit vector equality function invokes the bit equality function defined above:>>> @synthesize
... def equals(xs: bits(8), ys: bits(8)) -> bit:
...     z = 1
...     for i in range(8):
...         z = z & equal(xs[i], ys[i])
...     return z
>>> bs = [0, 1, 1, 0, 1, 0, 1, 0]
>>> equals.circuit.evaluate([bs, bs])
[[1]]
>>> equals.circuit.count() # Number of gates in circuit.
66Because a circuit is synthesized via standard execution of a decorated Python function, all native Python language features (and even external libraries) can be employed. The most important constraint (which is the responsibility of the programmer to maintain) is that the execution of the function (i.e., theflow of control) should not depend on thevaluesof the inputs bits. The alternative implementation below demonstrates that recursion and higher-order functions can be used within decorated functions:>>> from functools import reduce
>>> @synthesize
... def equals(xs: bits(8), ys: bits(8)) -> bit:
...     es = [equal(x, y) for (x, y) in zip(xs, ys)]
...     return reduce((lambda e0, e1: e0 & e1), es)
>>> bs = [0, 1, 1, 0, 1, 0, 1, 0]
>>> equals.circuit.evaluate([bs, list(reversed(bs))])
[[0]]
>>> equals.circuit.count() # Number of gates in circuit.
64Amore complex exampleinvolving an implementation of SHA-265 that conforms to theFIPS 180-4 specificationis found in thetesting scriptthat accompanies this library. The SHA-256 example is also described in arelevant report.DevelopmentAll installation and development dependencies are fully specified inpyproject.toml. Theproject.optional-dependenciesobject is used tospecify optional requirementsfor various development tasks. This makes it possible to specify additional options (such asdocs,lint, and so on) when performing installation usingpip:python -m pip install .[docs,lint]DocumentationThe documentation can be generated automatically from the source files usingSphinx:python -m pip install .[docs]
cd docs
sphinx-apidoc -f -E --templatedir=_templates -o _source .. && make htmlTesting and ConventionsAll unit tests are executed and their coverage is measured when usingpytest(see thepyproject.tomlfile for configuration details):python -m pip install .[test]
python -m pytestThe subset of the unit tests included in the module itself and thedocumentation examplesthat appear in the testing script can be executed separately usingdoctest:python src/circuitry/circuitry.py -v
python test/test_circuitry.py -vStyle conventions are enforced usingPylint:python -m pip install .[lint]
python -m pylint src/circuitry test/test_circuitry.pyContributionsIn order to contribute to the source code, open an issue or submit a pull request on theGitHub pagefor this library.VersioningBeginning with version 0.1.0, the version number format for this library and the changes to the library associated with version number increments conform withSemantic Versioning 2.0.0.PublishingThis library can be published as apackage on PyPIby a package maintainer. First, install the dependencies required for packaging and publishing:python -m pip install .[publish]Ensure that the correct version number appears inpyproject.toml, and that any links in this README document to the Read the Docs documentation of this package (or its dependencies) have appropriate version numbers. Also ensure that the Read the Docs project for this library has anautomation rulethat activates and sets as the default all tagged versions. Create and push a tag for this version (replacing?.?.?with the version number):git tag ?.?.?
git push origin ?.?.?Remove any old build/distribution files and package the source into a distribution archive:rm -rf build dist src/*.egg-info
python -m build --sdist --wheel .Finally, upload the package distribution archive toPyPIusing thetwinepackage:python -m twine upload dist/*