Support of PDK in HA and FA

This commit is contained in:
Vojta Mrazek 2022-01-13 12:37:09 +01:00
parent 18b44226d8
commit d641595c3e
6 changed files with 139 additions and 13 deletions

View File

@ -1,34 +1,69 @@
# ArithsGen tool for arithmetic circuits generation
### FIT BUT bachelor's degree project
## Description
ArithsGen presents an open source tool that enables generation of various arithmetic circuits along with the possibility to export them to various representations which all serve their specific purpose. C language for easy simulation, Verilog for logic synthesis, BLIF for formal verification possibilities and CGP to enable further global optimization.
### Usage
```bash
python3 ariths_gen.py
python3 generate_test.py
cd test_circuits
ls
```
### Example of generation
```py
#Example generation of Verilog representation of 8-bit unsigned dadda multiplier that uses cla to provide the final product
a = Bus(N=8, prefix="a_bus")
b = Bus(N=8, prefix="b_bus")
u_dadda = UnsignedDaddaMultiplier(a=a, b=b, prefix="h_u_dadda_cla8", unsigned_adder_class_name=UnsignedCarryLookaheadAdder)
u_dadda.get_v_code_hier(open("h_u_dadda_cla8.v", "w"))
```
### Simple arithmetic circuits
See ()[rca.py]
### Complex circuits
```py
from ariths_gen.core.arithmetic_circuits.arithmetic_circuit import ArithmeticCircuit
from ariths_gen.core.arithmetic_circuits import GeneralCircuit
from ariths_gen.wire_components import Bus, Wire
from ariths_gen.multi_bit_circuits.adders import UnsignedRippleCarryAdder
from ariths_gen.multi_bit_circuits.multipliers import UnsignedArrayMultiplier, UnsignedDaddaMultiplier
import os
class MAC(GeneralCircuit):
def __init__(self, a: Bus, b: Bus, r: Bus, prefix: str = "", name: str = "mac", **kwargs):
super().__init__(prefix=prefix, name=name, out_N=2*a.N+1, inputs=[a, b, r], **kwargs)
assert a.N == b.N
assert r.N == 2 * a.N
self.mul = self.add_component(UnsignedArrayMultiplier(a=a, b=b, prefix=self.prefix, name=f"u_arrmul{a.N}", inner_component=True))
self.add = self.add_component(UnsignedRippleCarryAdder(a=r, b=self.mul.out, prefix=self.prefix, name=f"u_rca{r.N}", inner_component=True))
self.out.connect_bus(connecting_bus=self.add.out)
# usage
if __name__ == "__main__":
os.makedirs("test_circuits/mac", exist_ok=True)
mymac = MAC(Bus("a", 8), Bus("b", 8), Bus("acc", 16))
mymac.get_v_code_hier(open("test_circuits/mac/mac_hier.v", "w"))
mymac.get_c_code_hier(open("test_circuits/mac/mac_hier.c", "w"))
mymac.get_c_code_flat(open("test_circuits/mac/mac_flat.c", "w"))
```
## Documentation
Code documentation is provided using **pdoc** documentation generator tool. Source: https://pdoc3.github.io/pdoc/.
https://ehw-fit.github.io/ariths-gen/
### Installation
```bash
pip3 install pdoc3
## Supporting various PDK kits
When one uses a specific process design kit (PDK), it is not effective to implement half- and full-adders using two-inputs logic gates. These circuits are directly implemented as CMOS modules and are more effective than heuristic optimization by synthesis tool. If you want to use for example FreePDK45 library, you can call a following function before verilog code generating.
```py
from ariths_gen import set_pdk45_library
set_pdk45_library()
```
### Usage
```bash
pdoc --html ariths_gen
```
You can add a support of arbitrary PDK (see an [example](ariths_gen/pdk.py) ).
## Formal verification
The `yosys_equiv_check.sh` script enables to formally check the equivalence of generated Verilog and BLIF representations of the same circuit.
@ -51,7 +86,6 @@ For more detailed description of script's usage, use help.
## CGP testing
The `chr2c.py` script converts the input CGP chromosome generated by ArithsGen to the corresponding C code and prints it to standard output.
It is a modified version of a script originally authored by Vojtech Mrazek.
### Usage
```bash

View File

@ -14,3 +14,5 @@ from .multi_bit_circuits import (
approximate_multipliers,
dividers
)
from .pdk import *

View File

@ -23,6 +23,8 @@ class FullAdder(ThreeInputOneBitCircuit):
c (Wire, optional): Carry input wire. Defaults to Wire(name="cin").
prefix (str, optional): Prefix name of full adder. Defaults to "fa".
"""
use_verilog_instance = False
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), c: Wire = Wire(name="cin"), prefix: str = "fa"):
super().__init__(a, b, c, prefix)
# 2 wires for component's bus output (sum, cout)
@ -50,6 +52,40 @@ class FullAdder(ThreeInputOneBitCircuit):
self.out.connect(1, obj_or.out)
def get_init_v_flat(self):
""" support of custom PDK """
if not self.use_verilog_instance:
return super().get_init_v_flat()
return " " + self.use_verilog_instance.format(
**{
"unit": self.prefix,
"wirea": self.a.prefix,
"wireb": self.b.prefix,
"wirec": self.c.prefix,
"wireys": self.get_sum_wire().prefix,
"wireyc": self.get_carry_wire().prefix,
}
) + "\n"
def get_self_init_v_hier(self):
""" support of custom PDK """
if not self.use_verilog_instance:
return super().get_self_init_v_hier()
unique_out_wires = []
for o in self.out.bus:
unique_out_wires.append(o.name+"_outid"+str(self.out.bus.index(o))) if o.is_const() or o.name in [self.a.name, self.b.name] else unique_out_wires.append(o.name)
return " " + self.use_verilog_instance.format(**{
"unit": self.prefix,
"wirea": self.a.name,
"wireb": self.b.name,
"wirec": self.c.name,
"wireys": unique_out_wires[0],
"wireyc": unique_out_wires[1],
}) + "\n"
class FullAdderPG(ThreeInputOneBitCircuit):
"""Class representing modified three input one bit full adder with propagate/generate logic.

View File

@ -21,6 +21,8 @@ class HalfAdder(TwoInputOneBitCircuit):
b (Wire, optional): Second input wire. Defaults to Wire(name="b").
prefix (str, optional): Prefix name of half adder. Defaults to "ha".
"""
use_verilog_instance = False
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "ha"):
super().__init__(a, b, prefix)
# 2 wires for component's bus output (sum, cout)
@ -38,6 +40,38 @@ class HalfAdder(TwoInputOneBitCircuit):
self.add_component(obj_and)
self.out.connect(1, obj_and.out)
def get_init_v_flat(self):
""" support of custom PDK """
if not self.use_verilog_instance:
return super().get_init_v_flat()
return " " + self.use_verilog_instance.format(
**{
"unit": self.prefix,
"wirea": self.a.prefix,
"wireb": self.b.prefix,
"wires": self.get_sum_wire().prefix,
"wirec": self.get_carry_wire().prefix,
}
) + "\n"
def get_self_init_v_hier(self):
""" support of custom PDK """
if not self.use_verilog_instance:
return super().get_self_init_v_hier()
unique_out_wires = []
for o in self.out.bus:
unique_out_wires.append(o.name+"_outid"+str(self.out.bus.index(o))) if o.is_const() or o.name in [self.a.name, self.b.name] else unique_out_wires.append(o.name)
return " " + self.use_verilog_instance.format(**{
"unit": self.prefix,
"wirea": self.a.name,
"wireb": self.b.name,
"wireys": unique_out_wires[0],
"wireyc": unique_out_wires[1],
}) + "\n"
class PGLogicBlock(TwoInputOneBitCircuit):
"""Class representing two input one bit propagate/generate logic block.

18
ariths_gen/pdk.py Normal file
View File

@ -0,0 +1,18 @@
"""
Support of custom PDK
This file defines functions for generating of full and half adders
directly on the level of CMOS modules.
You may add your own modules as in example in set_pdk45_library()
Please call this function before calling get_verilog_code_XXX()
"""
from .one_bit_circuits import (
one_bit_components
)
def set_pdk45_library():
one_bit_components.FullAdder.use_verilog_instance = "FAX1 {unit} (.A({wirea}), .B({wireb}), .C({wirec}), .YS({wireys}), .YC({wireyc}))"
one_bit_components.HalfAdder.use_verilog_instance = "HAX1 {unit} (.A({wirea}), .B({wireb}), .YS({wireys}), .YC({wireyc}))"

4
yosys_equiv_check.sh Normal file → Executable file
View File

@ -83,6 +83,8 @@ else
if [[ "$TOP_MODULE" != $(echo $BLIF_FILE | cut -c1-"$((${#BLIF_FILE}-5))") ]]; then
echo "Input files have different names! Do they describe the same circuit design?"
echo "For proper equivalence check, both designs should have the same name used for their filenames and also for their top module designs."
echo $TOP_MODULE
echo $(echo $BLIF_FILE | cut -c1-"$((${#BLIF_FILE}-5))")
echo
echo "Type -h | --help for more information."
exit 2
@ -136,4 +138,4 @@ else
equiv_simple
equiv_status -assert
"
fi
fi