pyAiger: A python library for manipulating sequential and
combinatorial circuits.
Table of Contents
About PyAiger
- Q: How is Py-Aiger pronounced? A: Like "pie" + "grrr".
- Q: Why python? Aren't you worried about performance?! A: No. The goals of this library are ease of use and hackability.
- Q: No, I'm really concerned about performance! A: This library is not suited to implement logic solvers. For everything else, such as the creation and manipulation of circuits with many thousands of gates in between solver calls, the library is really fast enough.
- Q: Where does the name come from? A: Aiger is a popular circuit format. The format is used in hardware model checking, synthesis, and is supported by ABC. The name is a combination of AIG (standing for And-Inverter-Graph) and the mountain Eiger.
Installation
If you just need to use aiger
, you can just run:
$ pip install py-aiger
For developers, note that this project uses the
poetry python package/dependency
management tool. Please familarize yourself with it and then
run:
$ poetry install
Usage
import aiger
x, y, z, w = aiger.atoms('x', 'y', 'z', 'w')
expr1 = z.implies(x & y)
expr2 = z & w
circ1 = expr1.with_output('z') \ # Get AIG for expr1 with output 'z'.
.aig
circ2 = circ1 >> circ2 # Feed outputs of circ1 into circ2.
Boolean Expression DSL
While powerful, when writing combinatorial circuits, the Sequential
Circuit DSL can be somewhat clumsy. For this common usecase, we have
developed the Boolean Expression DSL. All circuits generated this way
have a single output.
import aiger
x, y, z = aiger.atoms('x', 'y', 'z')
expr1 = x & y
expr2 = x | y
expr3 = x ^ y
expr4 = x == y
expr5 = x.implies(y)
expr6 = ~x
expr7 = aiger.ite(x, y, z)
expr8 = x & True
expr9 = x & False
expr10 = expr5.with_output('x_implies_y')
assert expr10.output == 'x_implies_y'
circ = x.aig
expr10 = aiger.BoolExpr(circ)
Sequential Circuit DSL
import aiger
from aiger import utils
aig1 = aiger.load(path_to_aig1_file.aag)
aig2 = aiger.load(path_to_aig2_file.aag)
Sequential composition
aig3 = aig1 >> aig2
Parallel composition
aig4 = aig1 | aig2
Circuits with Latches and Delayed Feedback
Sometimes one requires some outputs to be feed back into the circuits
as time delayed inputs. This can be accomplished using the loopback
method. This method takes in a variable number of dictionaries
encoding how to wire an input to an output. The wiring dictionaries
with the following keys and default values:
Key | Default | Meaning |
---|
input | | Input port |
output | | Output port |
latch | input | Latch name |
init | True | Initial latch value |
keep_output | True | Keep loopbacked output as output |
aig5 = aig1.loopback({
"input": "x", "output": "y",
})
aig6 = aig1.loopback({
"input": "x", "output": "y",
}, {
"input": "z", "output": "z", "latch": "z_latch",
"init": False, "keep_outputs": False
})
Relabeling
There are two syntaxes for relabeling. The first uses indexing
syntax in a nod to notation often used variable substition in math.
The syntax is the relabel method, which is preferable when one wants
to be explicit, even for those not familar with py-aiger
.
aig1['i', {'x': 'z'}]
aig1.relabel('input', {'x': 'z'})
aig1['o', {'y': 'w'}]
aig1.relabel('output', {'y': 'w'})
aig1['l', {'l1': 'l2'}]
aig1.relabel('latch', {'l1': 'l2'})
Evaluation
aig3(inputs={'x':True, 'y':False})
sim = aig3.simulate([{'x': 0, 'y': 0},
{'x': 1, 'y': 2},
{'x': 3, 'y': 4}])
sim = aig3.simulator()
next(sim)
print(sim.send({'x': 0, 'y': 0}))
print(sim.send({'x': 1, 'y': 2}))
print(sim.send({'x': 3, 'y': 4}))
aig4 = aig3.unroll(steps=10, init=True)
Useful circuits
aig4 = aiger.source({'x': False}) >> aig3
aig4 = aig3 >> aiger.sink(['y'])
aig4 = aig3 >> aiger.tee({'y': ['y', 'w']})
aiger.common.eval_order(aig1)
aiger.to_aig(aig1)
Ecosystem
Stable
- py-aiger-bv: Extension of pyAiger for manipulating sequential bitvector circuits.
- py-aiger-cnf: BoolExpr to Object representing CNF. Mostly used for interfacing with py-aiger-sat.
- py-aiger-past-ltl: Converts Past Linear Temporal Logic to aiger circuits.
- py-aiger-coins: Library for creating circuits that encode discrete distributions.
- py-aiger-sat: Bridge between py-aiger and py-sat.
- py-aiger-bdd: Aiger <-> BDD bridge.
- py-aiger-gridworld: Create aiger circuits representing gridworlds.
- py-aiger-dfa: Convert between finite automata and sequential circuits.
Underdevelopment
Related Projects
- pyAig: Another python library
for working with AIGER circuits.