## Circuit Declarations

Circuit declarations are used to declare primitive built-in circuits.
The most common use for a circuit declaration is to declare a built-in verilog module.

The function
```python
C = DeclareCircuit( name, typesignature )
```
returns a class which is a subclass of `Circuit`.
This circuit can be instanced.
The type signature has the form `(name0, type0, name1, type1, ..., namen, typen)`
The types should be qualified as inputs or outputs.

For example,
```python
SB_LUT4 = DeclareCircuit('SB_LUT4',
               "I0", In(Bit),
               "I1", In(Bit),
               "I2", In(Bit),
               "I3", In(Bit),
               "O",  Out(Bit))
```
declares the Silicon Blue LUT4 primitive
that is built-in to the Lattice ice40 and yosys verilog compilers.
This primitive has 4 inputs each declared as `In(Bit)`,
and a single output declared as `Out(Bit)`.

To create `lut4` circuit instance on the FPGA, we instance `SB_LUT4`.
```python
lut4 = SB_LUT4(LUT_INIT=0xffff)
```
Here we pass in the 16-bit value which is used to initialize the LUT.

## Circuit Definitions

it is easy to add new circuit classes to Magma
using circuit definitions.

For example,
```python
FA = DefineCircuit('FullAdder', 'a', In(Bit), 'b', In(Bit), 'cin', In(Bit), 's', Out(Bit), 'co', Out(Bit))
s = FA.a ^ FA.b ^ FA.cin
wire(s, FA.s)
cout = (FA.a & FA.b) | (FA.b & FA.cin) | (FA.a & FA.cin)
wire(cout, FA.cout)
EndCircuit()
```
`FA` is a subclass of `Circuit`. 
It has been enhanced to include the arguments in the function signature,
in this case the inputs `a`, `b`, `cin` and the outputs `s` and `cout`.
Inside the circuit definition we can instance circuits and wire them together.

Once `FA` has been defined, we can create circuit instances from it
```python
fa = FA()
```

`DefineCircuit` has the same function signature as `DeclareCircuit`.
```python
C = DefineCircuit( name, typesignature )
```
`EndCircuit` is needed to end the current circuit definition.
Note that it is possible to nest circuit definitions.

Note that circuit definitions are cached using the name of the circuit. 
Defining a circuit a second time with the same name returns the same circuit class.

## Circuit subclasses

The recommended way to create new circuits is to subclass Circuit.
```python
class FullAdder(Circuit):
    name = "FullAdder"
    IO = ["a", In(Bit), "b", In(Bit), "cin", In(Bit), "s", Out(Bit), "cout", Out(Bit)]
    @classmethod
    def definition(io):
        # Generate the sum
        s = io.a ^ io.b ^ io.cin
        wire(s, io.s)
        # Generate the carry
        cout = (io.a & io.b) | (io.b & io.cin) | (io.a & io.cin)
        wire(cout, io.cout)
```
The circuit signature is contained in the attributes of `FullAdder`,
in particular, `name` and `IO`.
The actual definition is inside the method `definition`.
Note that this is a class method.
Note also that the circuit being defined is passed as an argument to `definition`,
and the body of that function is identical to the code inside `DefineCircuit` and `EndCircuit`.

This magic is all done with python metaclasses.

## Verilog

It is useful to be able to declare circuits from verilog source.

We provide two utilities for doing this.
```python
modules = declare_from_verilog(source)
modules = declare_from_verilog_file(filename)
```
These functions return a list of Circuits, one for each module in the verilog file.
The circuits will have the same name and interface as the modules in the verilog file.
The verilog file is parsed using the python module `pyverilog`,
which must be installed.

Here is a simple example,
```python
from magma import declare_from_verilog

source = '''\
module CSA4 ( input [3:0] a,b,c, output [3:0] s, co);
   assign s = a ^ b ^c;
   assign co = a&b | b&c | a&c;
endmodule'''

CSA4 = declare_from_verilog(source)[0]
```

Another useful technique is to run a text templating engine over the verilog file before parsing.
```python
modules = DefineFromTemplatedVerilog(template, **kwargs)
modules = DefineFromTemplatedVerilogFile(templatefilename, **kwargs)
```
We use the `mako` templating engine.
The arguments `kwargs` appear in the global name space of the python code in the template.
These functions return a list of Circuits, one for each module in the verilog file.
The circuits will have the same name and interface as the modules in the verilog file.

```python
from magma import DefineFromTemplatedVerilog

source = '''\
module CSA${N} ( input [${N-1}:0] a,b,c, output [${N-1}:0] s, co );
   assign s = a ^ b ^c;
   assign co = a&b | b&c | a&c;
endmodule'''

CSA4 = DefineFromTemplatedVerilog(source, **dict(N=4))[0]
```

Examples using these two functions are in a [jupyter
notebook](https://github.com/phanrahan/magmathon/blob/master/notebooks/advanced/verilog.ipynb)