mirror of
https://github.com/ehw-fit/ariths-gen.git
synced 2025-04-10 17:22:11 +01:00
Added some code documentation and updated git action to generate it.
This commit is contained in:
parent
7a6d5213f8
commit
a336a683e7
2
.github/workflows/generate.yml
vendored
2
.github/workflows/generate.yml
vendored
@ -30,6 +30,8 @@ jobs:
|
||||
run: python -c "import sys; print(sys.version)"
|
||||
- name: Run generating
|
||||
run: python ariths_gen.py
|
||||
- name: Create documentation
|
||||
run: pdoc --html ariths_gen
|
||||
- name: Listing
|
||||
run: ls build
|
||||
- name: Listing2
|
||||
|
19
README.md
19
README.md
@ -5,7 +5,9 @@
|
||||
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
|
||||
python3 ariths_gen.py
|
||||
```bash
|
||||
python3 ariths_gen.py
|
||||
```
|
||||
|
||||
### Example of generation
|
||||
#Example of 8-bit unsigned dadda multiplier that uses rca to provide the final product
|
||||
@ -13,4 +15,17 @@ ArithsGen presents an open source tool that enables generation of various arithm
|
||||
b = Bus(N=8, prefix="b_bus")
|
||||
|
||||
u_dadda = UnsignedDaddaMultiplier(a=a, b=b, prefix="h_u_dadda_rca8", unsigned_adder_class_name=UnsignedRippleCarryAdder)
|
||||
u_dadda.get_v_code_hier(open("h_u_dadda_rca8.v", "w"))
|
||||
u_dadda.get_v_code_hier(open("h_u_dadda_rca8.v", "w"))
|
||||
|
||||
## Documentation
|
||||
Code documentation is provided using **pdoc** documentation generator tool. Source: https://pdoc3.github.io/pdoc/.
|
||||
|
||||
### Instalation
|
||||
```bash
|
||||
pip3 install pdoc3
|
||||
```
|
||||
|
||||
### Usage
|
||||
```bash
|
||||
pdoc --html ariths_gen
|
||||
```
|
@ -6,6 +6,10 @@ Script checks correct functionality of various architectures of unsigned/signed
|
||||
**Note** that these circuits were manually modified to allow such a testing (added main with nested loops and asserts)!
|
||||
|
||||
## Execute permission
|
||||
chmod +x c_tests.sh
|
||||
```bash
|
||||
chmod +x c_tests.sh
|
||||
```
|
||||
## Usage
|
||||
./c_tests.sh
|
||||
```bash
|
||||
./c_tests.sh
|
||||
```
|
@ -1,4 +1,4 @@
|
||||
from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||
LogicGate,
|
||||
AndGate,
|
||||
NandGate,
|
||||
@ -6,16 +6,18 @@ from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
NorGate,
|
||||
XorGate,
|
||||
XnorGate,
|
||||
NotGate
|
||||
NotGate
|
||||
)
|
||||
|
||||
from ariths_gen.wire_components import(
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
Bus
|
||||
)
|
||||
|
||||
""" ARITHMETIC CIRCUITS """
|
||||
|
||||
class ArithmeticCircuit():
|
||||
"""Class represents a general arithmetic circuit and ensures their generation to various representations.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.components = []
|
||||
self.circuit_wires = []
|
||||
@ -176,7 +178,7 @@ class ArithmeticCircuit():
|
||||
|
||||
def get_function_block_c(self):
|
||||
# Obtain proper adder name with its bit width
|
||||
adder_prefix = self.__class__(a=Bus("a") , b=Bus("b")).prefix + str(self.N)
|
||||
adder_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
adder_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=adder_prefix)
|
||||
return f"{adder_block.get_circuit_c()}\n\n"
|
||||
|
||||
@ -264,7 +266,7 @@ class ArithmeticCircuit():
|
||||
|
||||
def get_function_block_v(self):
|
||||
# Obtain proper adder name with its bit width
|
||||
adder_prefix = self.__class__(a=Bus("a") , b=Bus("b")).prefix + str(self.N)
|
||||
adder_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
adder_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=adder_prefix)
|
||||
return f"{adder_block.get_circuit_v()}\n\n"
|
||||
|
||||
@ -369,7 +371,7 @@ class ArithmeticCircuit():
|
||||
|
||||
def get_function_block_blif(self):
|
||||
# Obtain proper adder name with its bit width
|
||||
adder_prefix = self.__class__(a=Bus("a") , b=Bus("b")).prefix + str(self.N)
|
||||
adder_prefix = self.__class__(a=Bus("a"), b=Bus("b")).prefix + str(self.N)
|
||||
adder_block = self.__class__(a=Bus(N=self.N, prefix="a"), b=Bus(N=self.N, prefix="b"), prefix=adder_prefix)
|
||||
return f"{adder_block.get_circuit_blif()}"
|
||||
|
||||
@ -397,4 +399,4 @@ class ArithmeticCircuit():
|
||||
file_object.write(self.get_parameters_cgp())
|
||||
file_object.write(self.get_triplet_cgp())
|
||||
file_object.write(self.get_output_cgp())
|
||||
file_object.close()
|
||||
file_object.close()
|
||||
|
@ -1,8 +1,8 @@
|
||||
from .arithmetic_circuit import(
|
||||
from .arithmetic_circuit import (
|
||||
ArithmeticCircuit
|
||||
)
|
||||
|
||||
from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||
LogicGate,
|
||||
AndGate,
|
||||
NandGate,
|
||||
@ -10,18 +10,21 @@ from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
NorGate,
|
||||
XorGate,
|
||||
XnorGate,
|
||||
NotGate
|
||||
NotGate
|
||||
)
|
||||
|
||||
from ariths_gen.wire_components import(
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
Bus
|
||||
)
|
||||
|
||||
import math
|
||||
|
||||
""" MULTIPLIER CIRCUITS """
|
||||
|
||||
class MultiplierCircuit(ArithmeticCircuit):
|
||||
"""Class represents a general multiplier circuit derived from `ArithmeticCircuit` class.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
@ -84,7 +87,7 @@ class MultiplierCircuit(ArithmeticCircuit):
|
||||
column[-1] = NandGate(a=column[-1][0], b=column[-1][1], prefix=self.prefix+'_nand_'+str(column[-1][0].index)+'_'+str(column[-1][1].index))
|
||||
if len(column[2:-1]) != 0:
|
||||
column[2:-1] = [AndGate(a=column[i][0], b=column[i][1], prefix=self.prefix+'_and_'+str(column[i][0].index)+'_'+str(column[i][1].index)) for i in range(2, len(column)-1)]
|
||||
|
||||
|
||||
return column
|
||||
|
||||
def get_column_height(self, column_num: int):
|
||||
|
@ -1,8 +1,11 @@
|
||||
from .two_input_one_bit_circuit import(
|
||||
from .two_input_one_bit_circuit import (
|
||||
TwoInputOneBitCircuit
|
||||
)
|
||||
|
||||
|
||||
class ThreeInputOneBitCircuit(TwoInputOneBitCircuit):
|
||||
"""Class represents a general three input one bit circuit and implements their generation to various representations. It is derived from `TwoInputOneBitCircuit` class.
|
||||
"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
@ -17,7 +20,7 @@ class ThreeInputOneBitCircuit(TwoInputOneBitCircuit):
|
||||
def get_out_invocation_c(self, **kwargs):
|
||||
circuit_class = self.__class__()
|
||||
return "".join([f' {o.name} = ({circuit_class.prefix}({self.a.name}, {self.b.name}, {self.c.name}) >> {self.out.bus.index(o)}) & 0x01;\n' for o in self.out.bus])
|
||||
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
# FLAT VERILOG #
|
||||
# Module prototype with three inputs
|
||||
@ -49,4 +52,4 @@ class ThreeInputOneBitCircuit(TwoInputOneBitCircuit):
|
||||
# Chromosome prototype with three inputs
|
||||
def get_parameters_cgp(self):
|
||||
self.circuit_gates = self.get_circuit_gates()
|
||||
return f"{{3,2,1,{len(self.circuit_gates)},2,1,0}}"
|
||||
return f"{{3,2,1,{len(self.circuit_gates)},2,1,0}}"
|
||||
|
@ -1,8 +1,11 @@
|
||||
from .arithmetic_circuit import(
|
||||
from .arithmetic_circuit import (
|
||||
ArithmeticCircuit
|
||||
)
|
||||
|
||||
|
||||
class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
"""Class represents a general two input one bit circuit and implements their generation to various representations. It is derived from `ArithmeticCircuit` class.
|
||||
"""
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
@ -17,7 +20,7 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
|
||||
# Wires values initialization and assignment
|
||||
def get_init_c_flat(self):
|
||||
return "".join([i.get_assign_c(name=i.get_wire_value_c(name=i.name.replace(self.prefix+"_",""))) for i in self.inputs]) + \
|
||||
return "".join([i.get_assign_c(name=i.get_wire_value_c(name=i.name.replace(self.prefix+"_", ""))) for i in self.inputs]) + \
|
||||
"".join([f" {c.out.name} = {c.get_init_c_flat()};\n" for c in self.components])
|
||||
|
||||
# Generating flat C code representation of circuit
|
||||
@ -51,7 +54,7 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
return "".join([c[0].get_declaration_c() for c in self.circuit_wires])
|
||||
|
||||
def get_init_c_hier(self):
|
||||
return "".join([i.get_assign_c(name=i.get_wire_value_c(name=i.name.replace(self.prefix+"_",""))) for i in self.inputs]) + \
|
||||
return "".join([i.get_assign_c(name=i.get_wire_value_c(name=i.name.replace(self.prefix+"_", ""))) for i in self.inputs]) + \
|
||||
"".join([f" {c.out.name} = {c.get_gate_invocation_c(remove_prefix=False)}" for c in self.components])
|
||||
|
||||
def get_function_out_c_hier(self):
|
||||
@ -69,7 +72,7 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
|
||||
# Wires values initialization and assignment
|
||||
def get_init_v_flat(self):
|
||||
return "".join([i.get_assign_v(name=i.name.replace(self.prefix+"_","")) for i in self.inputs]) + \
|
||||
return "".join([i.get_assign_v(name=i.name.replace(self.prefix+"_", "")) for i in self.inputs]) + \
|
||||
"".join([f" assign {c.out.name} = {c.get_init_v_flat()};\n" for c in self.components])
|
||||
|
||||
# Generating flat Verilog code representation of circuit
|
||||
@ -100,7 +103,7 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
return "".join([c[0].get_declaration_v() for c in self.circuit_wires if c[0] not in self.out.bus])
|
||||
|
||||
def get_init_v_hier(self):
|
||||
return "".join([i.get_assign_v(name=i.name.replace(self.prefix+"_","")) for i in self.inputs])
|
||||
return "".join([i.get_assign_v(name=i.name.replace(self.prefix+"_", "")) for i in self.inputs])
|
||||
|
||||
def get_function_out_v_hier(self):
|
||||
return "".join([f"{c.get_gate_invocation_v(remove_prefix=False)}" for c in self.components])
|
||||
@ -114,7 +117,7 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
def get_wire_mapping_blif(self):
|
||||
# For unique mapping of all circuit's input interconnections
|
||||
self.get_circuit_wires()
|
||||
return "".join([i.get_assign_blif(name=i.name.replace(self.prefix+"_","")) for i in self.inputs])
|
||||
return "".join([i.get_assign_blif(name=i.name.replace(self.prefix+"_", "")) for i in self.inputs])
|
||||
|
||||
def get_function_blif_flat(self):
|
||||
return f"{self.get_wire_mapping_blif()}"+"".join([c.get_function_blif_flat() for c in self.components])
|
||||
@ -141,4 +144,4 @@ class TwoInputOneBitCircuit(ArithmeticCircuit):
|
||||
# FLAT CGP #
|
||||
def get_parameters_cgp(self):
|
||||
self.circuit_gates = self.get_circuit_gates()
|
||||
return f"{{2,2,1,{len(self.circuit_gates)},2,1,0}}"
|
||||
return f"{{2,2,1,{len(self.circuit_gates)},2,1,0}}"
|
||||
|
@ -1,12 +1,12 @@
|
||||
from ariths_gen.wire_components import(
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
Bus
|
||||
)
|
||||
from ariths_gen.core import(
|
||||
from ariths_gen.core import (
|
||||
ArithmeticCircuit,
|
||||
MultiplierCircuit
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import (
|
||||
HalfAdder,
|
||||
PGLogicBlock,
|
||||
ConstantWireValue0,
|
||||
@ -14,7 +14,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
FullAdder,
|
||||
FullAdderPG
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||
LogicGate,
|
||||
AndGate,
|
||||
NandGate,
|
||||
@ -25,7 +25,39 @@ from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
NotGate
|
||||
)
|
||||
|
||||
|
||||
class UnsignedCarryLookaheadAdder(ArithmeticCircuit):
|
||||
"""Class representing unsigned carry look-ahead adder.
|
||||
|
||||
Unsigned carry look-ahead adder represents faster adder circuit which is composed
|
||||
of more complex circuitry but provides much less propagation delay as opposed to rca.
|
||||
It is mainly composed of propagate/generate blocks and many AND/OR gates to calculate carries individually.
|
||||
|
||||
```
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ PG │ │ PG │ │ PG │ │ PG │
|
||||
│ block│ │ block│ │ block│ │ block│
|
||||
│ │ │ │ │ │ │ │
|
||||
└─┬──┬─┘ └─┬──┬─┘ └─┬──┬─┘ └─┬──┬─┘
|
||||
│ │ G3P3 │ │ G2P2 │ │ G1P1 │ │ G0P0
|
||||
┌─▼──▼───────▼──▼───────▼──▼───────▼──▼─┐
|
||||
│ Carry Lookahead logic │
|
||||
│ │
|
||||
└┬────┬───────┬──────────┬──────────┬───┘
|
||||
│ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
Cout S3 S1 S0 S0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned cla. Defaults to "u_cla".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_cla"):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
@ -49,7 +81,7 @@ class UnsignedCarryLookaheadAdder(ArithmeticCircuit):
|
||||
self.add_component(constant_wire_0)
|
||||
# Used as a first generate wire for obtaining next carry bits
|
||||
self.generate.append(constant_wire_0.out.get_wire())
|
||||
|
||||
|
||||
# Gradual addition of propagate/generate logic blocks and AND/OR gates for Cout bits generation, XOR gates for Sum bits generation
|
||||
for input_index in range(self.N):
|
||||
pg_block = PGLogicBlock(self.a.get_wire(input_index), self.b.get_wire(input_index), prefix=self.prefix+"_pg_logic"+str(input_index))
|
||||
@ -73,7 +105,7 @@ class UnsignedCarryLookaheadAdder(ArithmeticCircuit):
|
||||
obj_sum_xor = XorGate(pg_block.get_sum_wire(), self.get_previous_component(2).out, prefix=self.prefix+"_xor"+str(input_index))
|
||||
self.add_component(obj_sum_xor)
|
||||
self.out.connect(input_index, obj_sum_xor.out)
|
||||
|
||||
|
||||
# For each pg pair values algorithmically combine two input AND gates to replace multiple input gates (resolves fan-in issue)
|
||||
composite_and_gates = []
|
||||
# And combine AND gate pairs into OR gates
|
||||
@ -100,22 +132,54 @@ class UnsignedCarryLookaheadAdder(ArithmeticCircuit):
|
||||
composite_and_gates.append(obj_and)
|
||||
|
||||
composite_or_gates.append(composite_and_gates.pop())
|
||||
|
||||
|
||||
# Final OR gates cascade using generated AND gates representing multiple input AND gates (cascade of multiple two input ones)
|
||||
for a in range(len(composite_or_gates)-1):
|
||||
obj_or = OrGate(self.get_previous_component().out, composite_or_gates[a].out, prefix=self.prefix+"_or"+str(self.get_instance_num(cls=OrGate)))
|
||||
self.add_component(obj_or)
|
||||
|
||||
|
||||
# Carry bit generation
|
||||
obj_cout_or = OrGate(pg_block.get_generate_wire(), self.get_previous_component().out, prefix=self.prefix+"_or"+str(self.get_instance_num(cls=OrGate)))
|
||||
self.add_component(obj_cout_or)
|
||||
|
||||
|
||||
# Connecting last output bit to last cout
|
||||
if input_index == (self.N-1):
|
||||
self.out.connect(self.N, obj_cout_or.out)
|
||||
|
||||
|
||||
|
||||
class SignedCarryLookaheadAdder(UnsignedCarryLookaheadAdder, ArithmeticCircuit):
|
||||
"""Class representing signed carry look-ahead adder.
|
||||
|
||||
Signed carry look-ahead adder represents faster adder circuit which is composed
|
||||
of more complex circuitry but provides much less propagation delay as opposed to rca.
|
||||
It is mainly composed of propagate/generate blocks and many AND/OR gates to calculate carries individually.
|
||||
At last XOR gates are used to ensure proper sign extension.
|
||||
|
||||
```
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ PG │ │ PG │ │ PG │ │ PG │
|
||||
│ block│ │ block│ │ block│ │ block│
|
||||
│ │ │ │ │ │ │ │
|
||||
└─┬──┬─┘ └─┬──┬─┘ └─┬──┬─┘ └─┬──┬─┘
|
||||
│ │ G3P3 │ │ G2P2 │ │ G1P1 │ │ G0P0
|
||||
┌─▼──▼───────▼──▼───────▼──▼───────▼──▼─┐
|
||||
│ Carry Lookahead logic │
|
||||
│ with sign extension │
|
||||
└┬────┬───────┬──────────┬──────────┬───┘
|
||||
│ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
Cout S3 S1 S0 S0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed cla. Defaults to "s_cla".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_cla"):
|
||||
super().__init__(a=a, b=b, prefix=prefix)
|
||||
self.c_data_type = "int64_t"
|
||||
@ -125,4 +189,4 @@ class SignedCarryLookaheadAdder(UnsignedCarryLookaheadAdder, ArithmeticCircuit):
|
||||
self.add_component(sign_xor_1)
|
||||
sign_xor_2 = XorGate(sign_xor_1.out, self.get_previous_component(2).out, prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate)))
|
||||
self.add_component(sign_xor_2)
|
||||
self.out.connect(self.N, sign_xor_2.out)
|
||||
self.out.connect(self.N, sign_xor_2.out)
|
||||
|
@ -1,12 +1,12 @@
|
||||
from ariths_gen.wire_components import(
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
Bus
|
||||
)
|
||||
from ariths_gen.core import(
|
||||
from ariths_gen.core import (
|
||||
ArithmeticCircuit,
|
||||
MultiplierCircuit
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import (
|
||||
HalfAdder,
|
||||
PGLogicBlock,
|
||||
ConstantWireValue0,
|
||||
@ -14,7 +14,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
FullAdder,
|
||||
FullAdderPG
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||
LogicGate,
|
||||
AndGate,
|
||||
NandGate,
|
||||
@ -25,7 +25,43 @@ from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
NotGate
|
||||
)
|
||||
|
||||
|
||||
class UnsignedPGRippleCarryAdder(ArithmeticCircuit):
|
||||
"""Class representing unsigned ripple carry adder with propagate/generate logic.
|
||||
|
||||
Unsigned ripple carry adder with PG logic represents slightly different rca implementation
|
||||
of N-bit unsigned adder which is composed of N one bit full adders with P/G logic.
|
||||
|
||||
```
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ PG │ │ PG │ │ PG │ │ PG │
|
||||
│ FA │ │ FA │ │ FA │ │ FA │
|
||||
│ │ │ │ │ │ │ │
|
||||
└─┬──┬┬┘ └─┬┬┬──┘ └─┬┬┬──┘ └─┬┬┬──┘
|
||||
│ ││G3P3S3 │││G2P2S2 │││G1P1S1 │││ G0P0S0
|
||||
│ ┌▼▼───────▼▼▼─────────▼▼▼─────────▼▼▼──┐
|
||||
│ │ Group PG logic │
|
||||
│ │ │
|
||||
│ └─┬───────┬──────────┬──────────┬──────┘
|
||||
│ │ │ │ │
|
||||
┌─▼───▼───────▼──────────▼──────────▼──────┐
|
||||
│ Sum logic │
|
||||
│ │
|
||||
└┬────┬───────┬──────────┬──────────┬──────┘
|
||||
│ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
Cout S3 S1 S0 S0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned P/G rca. Defaults to "u_pg_rca".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_pg_rca"):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
@ -49,7 +85,7 @@ class UnsignedPGRippleCarryAdder(ArithmeticCircuit):
|
||||
obj_fa_cla = FullAdderPG(self.a.get_wire(input_index), self.b.get_wire(input_index), constant_wire_0.out.get_wire(), prefix=self.prefix+"_fa"+str(input_index))
|
||||
else:
|
||||
obj_fa_cla = FullAdderPG(self.a.get_wire(input_index), self.b.get_wire(input_index), self.get_previous_component().out, prefix=self.prefix+"_fa"+str(input_index))
|
||||
|
||||
|
||||
self.add_component(obj_fa_cla)
|
||||
self.out.connect(input_index, obj_fa_cla.get_sum_wire())
|
||||
|
||||
@ -57,13 +93,49 @@ class UnsignedPGRippleCarryAdder(ArithmeticCircuit):
|
||||
obj_or = OrGate(obj_and.out, self.get_previous_component().get_generate_wire(), prefix=self.prefix+"_or"+str(input_index))
|
||||
self.add_component(obj_and)
|
||||
self.add_component(obj_or)
|
||||
|
||||
|
||||
# Connecting last output bit to last cout
|
||||
if input_index == (self.N-1):
|
||||
self.out.connect(self.N, obj_or.out)
|
||||
|
||||
|
||||
class SignedPGRippleCarryAdder(UnsignedPGRippleCarryAdder, ArithmeticCircuit):
|
||||
"""Class representing signed ripple carry adder with propagate/generate logic.
|
||||
|
||||
Signed ripple carry adder with PG logic represents slightly different rca implementation
|
||||
of N-bit signed adder which is composed of N one bit full adders with P/G logic.
|
||||
At last XOR gates are used to ensure proper sign extension.
|
||||
|
||||
```
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ PG │ │ PG │ │ PG │ │ PG │
|
||||
│ FA │ │ FA │ │ FA │ │ FA │
|
||||
│ │ │ │ │ │ │ │
|
||||
└─┬──┬┬┘ └─┬┬┬──┘ └─┬┬┬──┘ └─┬┬┬──┘
|
||||
│ ││G3P3S3 │││G2P2S2 │││G1P1S1 │││ G0P0S0
|
||||
│ ┌▼▼───────▼▼▼─────────▼▼▼─────────▼▼▼──┐
|
||||
│ │ Group PG logic │
|
||||
│ │ │
|
||||
│ └─┬───────┬──────────┬──────────┬──────┘
|
||||
│ │ │ │ │
|
||||
┌─▼───▼───────▼──────────▼──────────▼──────┐
|
||||
│ Sum logic │
|
||||
│ with sign extension │
|
||||
└┬────┬───────┬──────────┬──────────┬──────┘
|
||||
│ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
Cout S3 S1 S0 S0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed P/G rca. Defaults to "s_pg_rca".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_pg_rca"):
|
||||
super().__init__(a=a, b=b, prefix=prefix)
|
||||
self.c_data_type = "int64_t"
|
||||
@ -73,4 +145,4 @@ class SignedPGRippleCarryAdder(UnsignedPGRippleCarryAdder, ArithmeticCircuit):
|
||||
self.add_component(sign_xor_1)
|
||||
sign_xor_2 = XorGate(sign_xor_1.out, self.get_previous_component(2).out, prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate)))
|
||||
self.add_component(sign_xor_2)
|
||||
self.out.connect(self.N, sign_xor_2.out)
|
||||
self.out.connect(self.N, sign_xor_2.out)
|
||||
|
@ -1,12 +1,12 @@
|
||||
from ariths_gen.wire_components import(
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
Bus
|
||||
)
|
||||
from ariths_gen.core import(
|
||||
from ariths_gen.core import (
|
||||
ArithmeticCircuit,
|
||||
MultiplierCircuit
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import (
|
||||
HalfAdder,
|
||||
PGLogicBlock,
|
||||
ConstantWireValue0,
|
||||
@ -14,7 +14,7 @@ from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
FullAdder,
|
||||
FullAdderPG
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||
LogicGate,
|
||||
AndGate,
|
||||
NandGate,
|
||||
@ -25,7 +25,34 @@ from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
NotGate
|
||||
)
|
||||
|
||||
|
||||
class UnsignedRippleCarryAdder(ArithmeticCircuit):
|
||||
"""Class representing unsigned ripple carry adder.
|
||||
|
||||
Unsigned ripple carry adder represents N-bit unsigned adder which is composed of
|
||||
N one bit adders, where first is a half adder and rest are full adders.
|
||||
|
||||
Its downside is its long propagation delay the bigger the circuit is.
|
||||
|
||||
```
|
||||
B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ │ C3│ │ C2│ │ C1│ │
|
||||
┌──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │
|
||||
│ │ │ │ │ │ │ │ │
|
||||
│ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
Cout S3 S2 S1 S0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned rca. Defaults to "u_rca".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_rca"):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
@ -48,14 +75,41 @@ class UnsignedRippleCarryAdder(ArithmeticCircuit):
|
||||
# Rest adders are full adders
|
||||
else:
|
||||
obj_adder = FullAdder(self.a.get_wire(input_index), self.b.get_wire(input_index), self.get_previous_component().get_carry_wire(), prefix=self.prefix+"_fa"+str(input_index))
|
||||
|
||||
|
||||
self.add_component(obj_adder)
|
||||
self.out.connect(input_index, obj_adder.get_sum_wire())
|
||||
if input_index == (self.N-1):
|
||||
self.out.connect(self.N, obj_adder.get_carry_wire())
|
||||
|
||||
|
||||
|
||||
class SignedRippleCarryAdder(UnsignedRippleCarryAdder, ArithmeticCircuit):
|
||||
"""Class representing signed ripple carry adder.
|
||||
|
||||
Signed ripple carry adder represents N-bit signed adder which is composed of
|
||||
N one bit adders, where first is a half adder and rest are full adders.
|
||||
At last XOR gates are used to ensure proper sign extension.
|
||||
|
||||
Its downside is its long propagation delay the bigger the circuit is.
|
||||
|
||||
```
|
||||
B3 A3 B3 A3 B2 A2 B1 A1 B0 A0
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐ ┌─▼──▼─┐
|
||||
│ SIGN │ C4│ │ C3│ │ C2│ │ C1│ │
|
||||
│Extend│◄──┤ FA │◄──┤ FA │◄──┤ FA │◄──┤ HA │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
└──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘
|
||||
▼ ▼ ▼ ▼ ▼
|
||||
Cout S3 S2 S1 S0
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed rca. Defaults to "s_rca".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_rca"):
|
||||
super().__init__(a=a, b=b, prefix=prefix)
|
||||
self.c_data_type = "int64_t"
|
||||
@ -65,4 +119,4 @@ class SignedRippleCarryAdder(UnsignedRippleCarryAdder, ArithmeticCircuit):
|
||||
self.add_component(sign_xor_1)
|
||||
sign_xor_2 = XorGate(sign_xor_1.out, self.get_previous_component(2).get_carry_wire(), prefix=self.prefix+"_xor"+str(self.get_instance_num(cls=XorGate)))
|
||||
self.add_component(sign_xor_2)
|
||||
self.out.connect(self.N, sign_xor_2.out)
|
||||
self.out.connect(self.N, sign_xor_2.out)
|
||||
|
@ -1,19 +1,19 @@
|
||||
from ariths_gen.wire_components import(
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
Bus
|
||||
)
|
||||
from ariths_gen.core import(
|
||||
from ariths_gen.core import (
|
||||
ArithmeticCircuit,
|
||||
MultiplierCircuit
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import (
|
||||
HalfAdder,
|
||||
ConstantWireValue0,
|
||||
ConstantWireValue1,
|
||||
FullAdder,
|
||||
FullAdderPG
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||
LogicGate,
|
||||
AndGate,
|
||||
NandGate,
|
||||
@ -24,8 +24,23 @@ from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
NotGate
|
||||
)
|
||||
|
||||
# MULTIPLIERS
|
||||
|
||||
class UnsignedArrayMultiplier(MultiplierCircuit):
|
||||
"""Class representing unsigned array multiplier.
|
||||
|
||||
Unsigned array multiplier represents N-bit multiplier composed of
|
||||
many AND gates and half/full adders to calculate partial products and
|
||||
gradually sum them.
|
||||
|
||||
Downside is its rather big area because it is composed of many logic gates.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned array multiplier. Defaults to "u_arrmul".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_arrmul"):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
@ -85,6 +100,21 @@ class UnsignedArrayMultiplier(MultiplierCircuit):
|
||||
|
||||
|
||||
class SignedArrayMultiplier(MultiplierCircuit):
|
||||
"""Class representing signed array multiplier.
|
||||
|
||||
Signed array multiplier represents N-bit multiplier composed of
|
||||
many AND/NAND gates and half/full adders to calculate partial products and
|
||||
gradually sum them.
|
||||
|
||||
Downside is its rather big area because it is composed of many logic gates.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed array multiplier. Defaults to "s_arrmul".
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_arrmul"):
|
||||
super().__init__()
|
||||
self.c_data_type = "int64_t"
|
||||
|
@ -1,20 +1,20 @@
|
||||
from ariths_gen.multi_bit_circuits.adders.ripple_carry_adder import UnsignedRippleCarryAdder
|
||||
from ariths_gen.wire_components import(
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
Bus
|
||||
)
|
||||
from ariths_gen.core import(
|
||||
from ariths_gen.core import (
|
||||
ArithmeticCircuit,
|
||||
MultiplierCircuit
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import (
|
||||
HalfAdder,
|
||||
ConstantWireValue0,
|
||||
ConstantWireValue1,
|
||||
FullAdder,
|
||||
FullAdderPG
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||
LogicGate,
|
||||
AndGate,
|
||||
NandGate,
|
||||
@ -25,7 +25,26 @@ from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
NotGate
|
||||
)
|
||||
|
||||
|
||||
class UnsignedDaddaMultiplier(MultiplierCircuit):
|
||||
"""Class representing unsigned dadda multiplier.
|
||||
|
||||
Unsigned dadda multiplier represents fast N-bit multiplier which utilizes
|
||||
the functionality of reduction algorithm proposed by Luigi Dadda.
|
||||
Dadda algorithm is described more in detail here:
|
||||
https://en.wikipedia.org/wiki/Dadda_multiplier
|
||||
|
||||
It is composed of much less inner components (half/full adders, AND gates) as opposed
|
||||
to e.g. wallace and array multipliers.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned dadda multiplier. Defaults to "u_dadda_rca".
|
||||
unsigned_adder_class_name (str, optional): Unsigned multi bit adder used to obtain final sums of products. Defaults to UnsignedRippleCarryAdder.
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_dadda_rca", unsigned_adder_class_name: str = UnsignedRippleCarryAdder):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
@ -103,7 +122,7 @@ class UnsignedDaddaMultiplier(MultiplierCircuit):
|
||||
# Final addition of remaining bits using chosen unsigned multi bit adder
|
||||
else:
|
||||
# Obtain proper adder name with its bit width (columns bit pairs minus the first alone bit)
|
||||
adder_prefix = unsigned_adder_class_name(a=a , b=b).prefix + str(len(self.columns)-1)
|
||||
adder_prefix = unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
|
||||
adder_a = Bus(prefix=f"{adder_prefix}_a", wires_list=[self.get_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"{adder_prefix}_b", wires_list=[self.get_column_wire(column=col, bit=2) for col in range(1, len(self.columns))])
|
||||
@ -114,6 +133,25 @@ class UnsignedDaddaMultiplier(MultiplierCircuit):
|
||||
|
||||
|
||||
class SignedDaddaMultiplier(MultiplierCircuit):
|
||||
"""Class representing signed dadda multiplier.
|
||||
|
||||
Signed dadda multiplier represents fast N-bit multiplier which utilizes
|
||||
the functionality of reduction algorithm proposed by Luigi Dadda and uses Baugh-Wooley algorithm
|
||||
to perform signed multiplication.
|
||||
Dadda algorithm is described more in detail here:
|
||||
https://en.wikipedia.org/wiki/Dadda_multiplier
|
||||
|
||||
It is composed of much less inner components (half/full adders, AND/NAND gates) as opposed
|
||||
to e.g. wallace and array multipliers.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed dadda multiplier. Defaults to "s_dadda_rca".
|
||||
unsigned_adder_class_name (str, optional): Unsigned multi bit adder used to obtain final sums of products. Defaults to UnsignedRippleCarryAdder.
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_dadda_rca", unsigned_adder_class_name: str = UnsignedRippleCarryAdder):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
@ -141,7 +179,7 @@ class SignedDaddaMultiplier(MultiplierCircuit):
|
||||
self.add_component(constant_wire_1)
|
||||
|
||||
# Adding constant wire with value 1 to achieve signedness
|
||||
# (adding constant value bit to last column (with one bit) to combine them in XOR gate to get the correct final multplication output bit at the end)
|
||||
# (adding constant value bit to last column (with one bit) to combine them in XOR gate to get the correct final multplication output bit at the end)
|
||||
self.columns[self.N].insert(1, constant_wire_1.out.get_wire())
|
||||
self.update_column_heights(curr_column=self.N, curr_height_change=1)
|
||||
|
||||
@ -202,7 +240,7 @@ class SignedDaddaMultiplier(MultiplierCircuit):
|
||||
# Final addition of remaining bits using chosen unsigned multi bit adder
|
||||
else:
|
||||
# Obtain proper adder name with its bit width (columns bit pairs minus the first alone bit)
|
||||
adder_prefix = unsigned_adder_class_name(a=a , b=b).prefix + str(len(self.columns)-1)
|
||||
adder_prefix = unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
|
||||
adder_a = Bus(prefix=f"{adder_prefix}_a", wires_list=[self.get_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"{adder_prefix}_b", wires_list=[self.get_column_wire(column=col, bit=2) for col in range(1, len(self.columns))])
|
||||
|
@ -1,20 +1,20 @@
|
||||
from ariths_gen.multi_bit_circuits.adders.ripple_carry_adder import UnsignedRippleCarryAdder
|
||||
from ariths_gen.wire_components import(
|
||||
from ariths_gen.wire_components import (
|
||||
Wire,
|
||||
Bus
|
||||
)
|
||||
from ariths_gen.core import(
|
||||
from ariths_gen.core import (
|
||||
ArithmeticCircuit,
|
||||
MultiplierCircuit
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import(
|
||||
from ariths_gen.one_bit_circuits.one_bit_components import (
|
||||
HalfAdder,
|
||||
ConstantWireValue0,
|
||||
ConstantWireValue1,
|
||||
FullAdder,
|
||||
FullAdderPG
|
||||
)
|
||||
from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
from ariths_gen.one_bit_circuits.logic_gates import (
|
||||
LogicGate,
|
||||
AndGate,
|
||||
NandGate,
|
||||
@ -25,7 +25,25 @@ from ariths_gen.one_bit_circuits.logic_gates import(
|
||||
NotGate
|
||||
)
|
||||
|
||||
|
||||
class UnsignedWallaceMultiplier(MultiplierCircuit):
|
||||
"""Class representing unsigned wallace multiplier.
|
||||
|
||||
Unsigned wallace multiplier represents fast N-bit multiplier which utilizes
|
||||
the functionality of wallace tree reduction algorithm proposed by Chris Wallace.
|
||||
Wallace tree algorithm is described more in detail here:
|
||||
https://en.wikipedia.org/wiki/Wallace_tree
|
||||
|
||||
It presents smaller circuit in area opposed to array multiplier but is slightly bigger then dadda because of less reduction stages.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of unsigned wallace multiplier. Defaults to "u_wallace_rca".
|
||||
unsigned_adder_class_name (str, optional): Unsigned multi bit adder used to obtain final sums of products. Defaults to UnsignedRippleCarryAdder.
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "u_wallace_rca", unsigned_adder_class_name: str = UnsignedRippleCarryAdder):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
@ -98,7 +116,7 @@ class UnsignedWallaceMultiplier(MultiplierCircuit):
|
||||
# Final addition of remaining bits using chosen unsigned multi bit adder
|
||||
else:
|
||||
# Obtain proper adder name with its bit width (columns bit pairs minus the first alone bit)
|
||||
adder_prefix = unsigned_adder_class_name(a=a , b=b).prefix + str(len(self.columns)-1)
|
||||
adder_prefix = unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
|
||||
adder_a = Bus(prefix=f"{adder_prefix}_a", wires_list=[self.get_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"{adder_prefix}_b", wires_list=[self.get_column_wire(column=col, bit=2) for col in range(1, len(self.columns))])
|
||||
@ -109,6 +127,24 @@ class UnsignedWallaceMultiplier(MultiplierCircuit):
|
||||
|
||||
|
||||
class SignedWallaceMultiplier(MultiplierCircuit):
|
||||
"""Class representing signed wallace multiplier.
|
||||
|
||||
Signed wallace multiplier represents fast N-bit multiplier which utilizes
|
||||
the functionality of wallace tree reduction algorithm proposed by Chris Wallace and uses Baugh-Wooley algorithm
|
||||
to perform signed multiplication.
|
||||
Wallace tree algorithm is described more in detail here:
|
||||
https://en.wikipedia.org/wiki/Wallace_tree
|
||||
|
||||
It presents smaller circuit in area opposed to array multiplier but is slightly bigger then dadda because of less reduction stages.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Bus): First input bus.
|
||||
b (Bus): Second input bus.
|
||||
prefix (str, optional): Prefix name of signed wallace multiplier. Defaults to "s_wallace_rca".
|
||||
unsigned_adder_class_name (str, optional): Unsigned multi bit adder used to obtain final sums of products. Defaults to UnsignedRippleCarryAdder.
|
||||
"""
|
||||
def __init__(self, a: Bus, b: Bus, prefix: str = "s_wallace_rca", unsigned_adder_class_name: str = UnsignedRippleCarryAdder):
|
||||
super().__init__()
|
||||
self.N = max(a.N, b.N)
|
||||
@ -134,7 +170,7 @@ class SignedWallaceMultiplier(MultiplierCircuit):
|
||||
self.add_component(constant_wire_1)
|
||||
|
||||
# Adding constant wire with value 1 to achieve signedness
|
||||
# (adding constant value bit to last column (with one bit) to combine them in XOR gate to get the correct final multplication output bit at the end)
|
||||
# (adding constant value bit to last column (with one bit) to combine them in XOR gate to get the correct final multplication output bit at the end)
|
||||
self.columns[self.N].insert(1, constant_wire_1.out.get_wire())
|
||||
self.update_column_heights(curr_column=self.N, curr_height_change=1)
|
||||
|
||||
@ -194,7 +230,7 @@ class SignedWallaceMultiplier(MultiplierCircuit):
|
||||
# Final addition of remaining bits using chosen unsigned multi bit adder
|
||||
else:
|
||||
# Obtain proper adder name with its bit width (columns bit pairs minus the first alone bit)
|
||||
adder_prefix = unsigned_adder_class_name(a=a , b=b).prefix + str(len(self.columns)-1)
|
||||
adder_prefix = unsigned_adder_class_name(a=a, b=b).prefix + str(len(self.columns)-1)
|
||||
|
||||
adder_a = Bus(prefix=f"{adder_prefix}_a", wires_list=[self.get_column_wire(column=col, bit=1) for col in range(1, len(self.columns))])
|
||||
adder_b = Bus(prefix=f"{adder_prefix}_b", wires_list=[self.get_column_wire(column=col, bit=2) for col in range(1, len(self.columns))])
|
||||
|
@ -1,10 +1,25 @@
|
||||
from ariths_gen.wire_components import Wire
|
||||
|
||||
""" LOGIC GATE COMPONENTS """
|
||||
|
||||
|
||||
# Two-input #
|
||||
class LogicGate():
|
||||
"""Class representing two input logic gates.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ FUNC │
|
||||
│ ├─►
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): First input wire.
|
||||
b (Wire): Second input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "gate".
|
||||
"""
|
||||
def __init__(self, a: Wire, b: Wire, prefix: str = "gate"):
|
||||
self.a = Wire(name=prefix+"_"+a.name.replace(prefix+"_", ""), value=a.value)
|
||||
self.b = Wire(name=prefix+"_"+b.name.replace(prefix+"_", ""), value=b.value)
|
||||
@ -154,6 +169,23 @@ class LogicGate():
|
||||
|
||||
|
||||
class InvertedLogicGate(LogicGate):
|
||||
"""Class representing two input inverted logic gates.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ FUNC │
|
||||
│ │O──►
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): First input wire.
|
||||
b (Wire): Second input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "gate".
|
||||
"""
|
||||
def __init__(self, a: Wire, b: Wire, prefix: str = "gate"):
|
||||
super().__init__(a, b, prefix)
|
||||
|
||||
@ -172,6 +204,24 @@ class InvertedLogicGate(LogicGate):
|
||||
|
||||
|
||||
class AndGate(LogicGate):
|
||||
"""Class representing two input and gate.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ & │
|
||||
│ ├─►
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): First input wire.
|
||||
b (Wire): Second input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "".
|
||||
outid (int, optional): Index of output wire. Defaults to 0.
|
||||
"""
|
||||
def __init__(self, a: Wire, b: Wire, prefix: str = "", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = "and_gate"
|
||||
@ -186,6 +236,24 @@ class AndGate(LogicGate):
|
||||
|
||||
|
||||
class NandGate(InvertedLogicGate):
|
||||
"""Class representing two input nand gate.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ & │
|
||||
│ │O──►
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): First input wire.
|
||||
b (Wire): Second input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "".
|
||||
outid (int, optional): Index of output wire. Defaults to 0.
|
||||
"""
|
||||
def __init__(self, a: Wire, b: Wire, prefix: str = "", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = "nand_gate"
|
||||
@ -200,6 +268,24 @@ class NandGate(InvertedLogicGate):
|
||||
|
||||
|
||||
class OrGate(LogicGate):
|
||||
"""Class representing two input or gate.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ ≥1 │
|
||||
│ ├─►
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): First input wire.
|
||||
b (Wire): Second input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "".
|
||||
outid (int, optional): Index of output wire. Defaults to 0.
|
||||
"""
|
||||
def __init__(self, a: Wire, b: Wire, prefix: str = "", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = "or_gate"
|
||||
@ -214,6 +300,24 @@ class OrGate(LogicGate):
|
||||
|
||||
|
||||
class NorGate(InvertedLogicGate):
|
||||
"""Class representing two input nor gate.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ ≥1 │
|
||||
│ │O──►
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): First input wire.
|
||||
b (Wire): Second input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "".
|
||||
outid (int, optional): Index of output wire. Defaults to 0.
|
||||
"""
|
||||
def __init__(self, a: Wire, b: Wire, prefix: str = "", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = "nor_gate"
|
||||
@ -228,6 +332,24 @@ class NorGate(InvertedLogicGate):
|
||||
|
||||
|
||||
class XorGate(LogicGate):
|
||||
"""Class representing two input xor gate.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ =1 │
|
||||
│ ├─►
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): First input wire.
|
||||
b (Wire): Second input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "".
|
||||
outid (int, optional): Index of output wire. Defaults to 0.
|
||||
"""
|
||||
def __init__(self, a: Wire, b: Wire, prefix: str = "", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = "xor_gate"
|
||||
@ -242,6 +364,24 @@ class XorGate(LogicGate):
|
||||
|
||||
|
||||
class XnorGate(InvertedLogicGate):
|
||||
"""Class representing two input xnor gate.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ =1 │
|
||||
│ │O──►
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): First input wire.
|
||||
b (Wire): Second input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "".
|
||||
outid (int, optional): Index of output wire. Defaults to 0.
|
||||
"""
|
||||
def __init__(self, a: Wire, b: Wire, prefix: str = "", outid: int = 0):
|
||||
super().__init__(a, b, prefix)
|
||||
self.gate_type = "xnor_gate"
|
||||
@ -257,6 +397,23 @@ class XnorGate(InvertedLogicGate):
|
||||
|
||||
# Single-input #
|
||||
class NotGate(InvertedLogicGate):
|
||||
"""Class representing one input not gate.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
│ 1 │
|
||||
──►│ │O─►
|
||||
│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire): Input wire.
|
||||
prefix (str, optional): Prefix name of logic gate. Defaults to "".
|
||||
outid (int, optional): Index of output wire. Defaults to 0.
|
||||
"""
|
||||
def __init__(self, a: Wire, prefix: str = "", outid: int = 0):
|
||||
self.gate_type = "not_gate"
|
||||
self.cgp_function = 1
|
||||
|
@ -2,8 +2,26 @@ from ariths_gen.core import ThreeInputOneBitCircuit
|
||||
from ariths_gen.one_bit_circuits.logic_gates import LogicGate, AndGate, NandGate, OrGate, NorGate, XorGate, XnorGate, NotGate
|
||||
from ariths_gen.wire_components import Wire, Bus
|
||||
|
||||
# THREE INPUT CIRCUITS
|
||||
|
||||
class FullAdder(ThreeInputOneBitCircuit):
|
||||
"""Class representing three input one bit full adder.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ ├─► Sum
|
||||
──►│ │
|
||||
──►│ ├─► Cout
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire, optional): First input wire. Defaults to Wire(name="a").
|
||||
b (Wire, optional): Second input wire. Defaults to Wire(name="b").
|
||||
c (Wire, optional): Carry input wire. Defaults to Wire(name="cin").
|
||||
prefix (str, optional): Prefix name of full adder. Defaults to "fa".
|
||||
"""
|
||||
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), c: Wire = Wire(name="cin"), prefix: str = "fa"):
|
||||
super().__init__()
|
||||
self.c_data_type = "uint8_t"
|
||||
@ -38,6 +56,24 @@ class FullAdder(ThreeInputOneBitCircuit):
|
||||
|
||||
|
||||
class FullAdderPG(ThreeInputOneBitCircuit):
|
||||
"""Class representing modified three input one bit full adder with propagate/generate logic.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ ├─► P
|
||||
──►│ ├─► G
|
||||
──►│ ├─► Sum
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire, optional): First input wire. Defaults to Wire(name="a").
|
||||
b (Wire, optional): Second input wire. Defaults to Wire(name="b").
|
||||
c (Wire, optional): Carry input wire. Defaults to Wire(name="cin").
|
||||
prefix (str, optional): Prefix name of full adder. Defaults to "fa_cla".
|
||||
"""
|
||||
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), c: Wire = Wire(name="cin"), prefix: str = "fa_cla"):
|
||||
super().__init__()
|
||||
self.c_data_type = "uint8_t"
|
||||
@ -61,7 +97,7 @@ class FullAdderPG(ThreeInputOneBitCircuit):
|
||||
sum_xor = XorGate(propagate_xor.out, c, prefix=self.prefix, outid=2)
|
||||
self.add_component(sum_xor)
|
||||
self.out.connect(2, sum_xor.out)
|
||||
|
||||
|
||||
def get_propagate_wire(self):
|
||||
return self.out.get_wire(0)
|
||||
|
||||
@ -69,4 +105,4 @@ class FullAdderPG(ThreeInputOneBitCircuit):
|
||||
return self.out.get_wire(1)
|
||||
|
||||
def get_sum_wire(self):
|
||||
return self.out.get_wire(2)
|
||||
return self.out.get_wire(2)
|
||||
|
@ -2,8 +2,25 @@ from ariths_gen.core import TwoInputOneBitCircuit
|
||||
from ariths_gen.one_bit_circuits.logic_gates import LogicGate, AndGate, NandGate, OrGate, NorGate, XorGate, XnorGate, NotGate
|
||||
from ariths_gen.wire_components import Wire, Bus
|
||||
|
||||
# TWO INPUT CIRCUITS
|
||||
|
||||
class HalfAdder(TwoInputOneBitCircuit):
|
||||
"""Class representing two input one bit half adder.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ ├─► Sum
|
||||
│ │
|
||||
──►│ ├─► Cout
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire, optional): First input wire. Defaults to Wire(name="a").
|
||||
b (Wire, optional): Second input wire. Defaults to Wire(name="b").
|
||||
prefix (str, optional): Prefix name of full adder. Defaults to "ha".
|
||||
"""
|
||||
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "ha"):
|
||||
super().__init__()
|
||||
self.c_data_type = "uint8_t"
|
||||
@ -27,6 +44,23 @@ class HalfAdder(TwoInputOneBitCircuit):
|
||||
|
||||
|
||||
class PGLogicBlock(TwoInputOneBitCircuit):
|
||||
"""Class representing two input one bit propagate/generate logic block.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ ├─► P
|
||||
│ │
|
||||
──►│ ├─► G
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire, optional): First input wire. Defaults to Wire(name="a").
|
||||
b (Wire, optional): Second input wire. Defaults to Wire(name="b").
|
||||
prefix (str, optional): Prefix name of full adder. Defaults to "pg_logic".
|
||||
"""
|
||||
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "pg_logic"):
|
||||
super().__init__()
|
||||
self.c_data_type = "uint8_t"
|
||||
@ -57,7 +91,25 @@ class PGLogicBlock(TwoInputOneBitCircuit):
|
||||
def get_sum_wire(self):
|
||||
return self.out.get_wire(2)
|
||||
|
||||
|
||||
class ConstantWireValue0(TwoInputOneBitCircuit):
|
||||
"""Class representing two input one bit constant wire with value 0 generation block.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ │
|
||||
│ ├─►0
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire, optional): First input wire. Defaults to Wire(name="a").
|
||||
b (Wire, optional): Second input wire. Defaults to Wire(name="b").
|
||||
prefix (str, optional): Prefix name of full adder. Defaults to "constant_wire_value_0".
|
||||
"""
|
||||
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "constant_wire_value_0"):
|
||||
super().__init__()
|
||||
self.c_data_type = "uint8_t"
|
||||
@ -83,6 +135,23 @@ class ConstantWireValue0(TwoInputOneBitCircuit):
|
||||
|
||||
|
||||
class ConstantWireValue1(TwoInputOneBitCircuit):
|
||||
"""Class representing two input one bit constant wire with value 1 generation block.
|
||||
|
||||
```
|
||||
┌──────┐
|
||||
──►│ │
|
||||
│ ├─►1
|
||||
──►│ │
|
||||
└──────┘
|
||||
```
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
a (Wire, optional): First input wire. Defaults to Wire(name="a").
|
||||
b (Wire, optional): Second input wire. Defaults to Wire(name="b").
|
||||
prefix (str, optional): Prefix name of full adder. Defaults to "constant_wire_value_1".
|
||||
"""
|
||||
def __init__(self, a: Wire = Wire(name="a"), b: Wire = Wire(name="b"), prefix: str = "constant_wire_value_1"):
|
||||
super().__init__()
|
||||
self.c_data_type = "uint8_t"
|
||||
|
@ -1,7 +1,17 @@
|
||||
from .wires import Wire
|
||||
|
||||
|
||||
class Bus():
|
||||
def __init__(self, prefix: str, N: int = 1, wires_list: list = None):
|
||||
"""Class representing bus of wires used as inputs/outputs of bigger circuits.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
prefix (str, optional): Prefix name of the bus. Defaults to "bus".
|
||||
N (int, optional): Number of wires in the bus. Defaults to 1.
|
||||
wires_list (list, optional): List of Wire objects used to clone one bus to another. Defaults to 0.
|
||||
"""
|
||||
def __init__(self, prefix: str = "bus", N: int = 1, wires_list: list = None):
|
||||
if wires_list is None:
|
||||
self.bus = [Wire(name=prefix+"_"+str(i), index=i) for i in range(N)]
|
||||
self.prefix = prefix
|
||||
@ -13,45 +23,119 @@ class Bus():
|
||||
|
||||
# Connecting output wire of the inner circuit component to the input of another component
|
||||
# (or to the wire of the circuit's output bus)
|
||||
def connect(self, out_wire_index: int, inner_component_out_wire: Wire):
|
||||
self.bus[out_wire_index] = inner_component_out_wire
|
||||
def connect(self, bus_wire_index: int, inner_component_out_wire: Wire):
|
||||
"""Connects given 'Wire' object to a 'bus_wire_index' within this bus.
|
||||
|
||||
Args:
|
||||
bus_wire_index (int): Index in bus to store given wire in.
|
||||
inner_component_out_wire (Wire): Wire of some other component (mostly its output) to store in the bus.
|
||||
"""
|
||||
self.bus[bus_wire_index] = inner_component_out_wire
|
||||
|
||||
def get_wire(self, wire_index: int = 0):
|
||||
"""Retrieves a wire from the bus by a given index.
|
||||
|
||||
Args:
|
||||
wire_index (int, optional): Index of wire to retrieve from the bus. Defaults to 0.
|
||||
|
||||
Returns:
|
||||
Wire: Return wire from the bus.
|
||||
"""
|
||||
return self.bus[wire_index]
|
||||
|
||||
def bus_extend(self, N: int, prefix: str = "bus"):
|
||||
"""Provides bus extension to contain more wires.
|
||||
|
||||
Args:
|
||||
N (int): Number of wires in the bus. Defaults to 1.
|
||||
prefix (str, optional): Prefix name of the bus. Defaults to "bus".
|
||||
"""
|
||||
if self.N < N:
|
||||
self.bus += [Wire(name=prefix+"_"+str(i), index=i) for i in range(self.N, N)]
|
||||
self.N = N
|
||||
|
||||
""" C CODE GENERATION """
|
||||
def get_declaration_c(self):
|
||||
"""Bus declaration in C code.
|
||||
|
||||
Returns:
|
||||
str: C code for declaration and initialization of bus name.
|
||||
"""
|
||||
if self.N > 8:
|
||||
return f" uint64_t {self.prefix} = 0;\n"
|
||||
else:
|
||||
return f" uint8_t {self.prefix} = 0;\n"
|
||||
|
||||
def get_wire_declaration_c(self):
|
||||
"""Declare each wire from the bus independently.
|
||||
|
||||
Returns:
|
||||
str: C code for declaration and initialization of bus wires.
|
||||
"""
|
||||
return "".join([w.get_declaration_c() for w in self.bus])
|
||||
|
||||
def get_wire_assign_c(self, bus_prefix: str = ""):
|
||||
"""Assign all bits from the bus to each individual wires in C code.
|
||||
|
||||
Args:
|
||||
bus_prefix (str, optional): Custom bus prefix to use for assignment. Defaults to "".
|
||||
|
||||
Returns:
|
||||
str: C code for bus wires assignments.
|
||||
"""
|
||||
bus_prefix = self.prefix if bus_prefix == "" else bus_prefix
|
||||
return "".join([w.get_assign_c(name=w.get_wire_value_c(name=bus_prefix, offset=self.bus.index(w))) for w in self.bus])
|
||||
|
||||
def return_wire_value_c(self, offset: int = 0):
|
||||
"""Retrieve wire value from desired index position in the bus.
|
||||
|
||||
Args:
|
||||
offset (int, optional): Offset position of the wire to be retrieved. Defaults to 0.
|
||||
"""
|
||||
self.get_wire(wire_index=offset).return_wire_value_c(offset=offset)
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
def get_wire_declaration_v(self):
|
||||
"""Declare each wire from the bus independently.
|
||||
|
||||
Returns:
|
||||
str: Verilog code for declaration of bus wires.
|
||||
"""
|
||||
return "".join([w.get_declaration_v() for w in self.bus])
|
||||
|
||||
def get_wire_assign_v(self, bus_prefix: str = ""):
|
||||
"""Assign all bits from the bus to each individual wires in Verilog code.
|
||||
|
||||
Args:
|
||||
bus_prefix (str, optional): Custom bus prefix to use for assignment. Defaults to "".
|
||||
|
||||
Returns:
|
||||
str: Verilog code for bus wires assignments.
|
||||
"""
|
||||
bus_prefix = self.prefix if bus_prefix == "" else bus_prefix
|
||||
return "".join([w.get_assign_v(name=self.prefix, offset=self.bus.index(w), array=True) for w in self.bus])
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
def get_wire_declaration_blif(self, array: bool = True):
|
||||
"""Declare each wire from the bus independently.
|
||||
|
||||
Argument `array` specifies whether to declare wires from bus by their offset e.g. out[0]
|
||||
or by their wire name e.g. out_0.
|
||||
Args:
|
||||
array (bool, optional): Determines in which manner bus wire names are declared. Defaults to True.
|
||||
|
||||
Returns:
|
||||
str: Blif code for declaration of bus wires.
|
||||
"""
|
||||
return "".join([w.get_declaration_blif(name=self.prefix, offset=self.bus.index(w), array=array) for w in self.bus])
|
||||
|
||||
def get_wire_assign_blif(self, output: bool = False):
|
||||
"""Assign all bits from the bus as each individual wires in Blif code.
|
||||
|
||||
Args:
|
||||
output (bool, optional): Specifies whether bus wires are used as outputs (assigned to) or as inputs (assigned from). Defaults to False.
|
||||
|
||||
Returns:
|
||||
str: Blif code for bus wires assignments.
|
||||
"""
|
||||
return "".join([w.get_assign_blif(name=self.prefix+f"[{self.bus.index(w)}]", output=output) for w in self.bus])
|
||||
|
@ -1,4 +1,14 @@
|
||||
class Wire():
|
||||
"""Class representing basic wire used to interconnect components.
|
||||
|
||||
Description of the __init__ method.
|
||||
|
||||
Args:
|
||||
name (str): Name of the wire.
|
||||
value (int, optional): Value it carries (0,1). Defaults to 0.
|
||||
index (int, optional): Index position of wire (mainly used for indexing within a bus). Defaults to 0.
|
||||
"""
|
||||
|
||||
def __init__(self, name: str, value: int = 0, index: int = 0):
|
||||
self.name = name
|
||||
if self.name.endswith("_"+str(index)):
|
||||
@ -10,23 +20,68 @@ class Wire():
|
||||
|
||||
""" C CODE GENERATION """
|
||||
def get_declaration_c(self):
|
||||
"""Wire declaration in C code.
|
||||
|
||||
Returns:
|
||||
str: C code for declaration and initialization of wire's name.
|
||||
"""
|
||||
return f" uint8_t {self.name} = {self.value};\n"
|
||||
|
||||
def get_wire_value_c(self, name: str = "", offset: int = 0):
|
||||
"""Access desired bit from wire represented in C code variable.
|
||||
|
||||
Args:
|
||||
name (str, optional): Name representing a wire. Defaults to "".
|
||||
offset (int, optional): Access desired wire bit from C code variable (used to access wire bits from buses). Defaults to 0.
|
||||
|
||||
Returns:
|
||||
str: C code bitwise shift to get bit from `offset` position in `w_name`.
|
||||
"""
|
||||
w_name = self.name if name == "" else name
|
||||
return f"(({w_name} >> {offset}) & 0x01)"
|
||||
|
||||
def get_assign_c(self, name: str):
|
||||
"""Assign (connect) the value of wire to another wire.
|
||||
|
||||
Args:
|
||||
name (str): Name of wire to assign value from.
|
||||
|
||||
Returns:
|
||||
str: C code for assignment of one wire to another.
|
||||
"""
|
||||
return f" {self.name} = {name};\n"
|
||||
|
||||
def return_wire_value_c(self, offset: int = 0):
|
||||
"""Retrieve bit value from wire and shift it to desired position for storing it within a bus.
|
||||
|
||||
Args:
|
||||
offset (int, optional): Used to shift wire value in order to be stored in proper location in bus. Defaults to 0.
|
||||
|
||||
Returns:
|
||||
str: C code bitwise shift of retrieved wire value.
|
||||
"""
|
||||
return f"({self.name} & 0x01) << {offset}"
|
||||
|
||||
""" VERILOG CODE GENERATION """
|
||||
def get_declaration_v(self):
|
||||
"""Wire declaration in Verilog code.
|
||||
|
||||
Returns:
|
||||
str: Verilog code for declaration of wire's name.
|
||||
"""
|
||||
return f" wire {self.name};\n"
|
||||
|
||||
def get_assign_v(self, name: str, offset: int = 0, array: bool = False):
|
||||
"""Assignment of wire value to another desired wire in Verilog.
|
||||
|
||||
Args:
|
||||
name (str): Name of wire/bus to assign value from.
|
||||
offset (int, optional): Used to retrieve desired wire from a bus. Defaults to 0.
|
||||
array (bool, optional): Tells whether wire value is assigned from within a bus or from basic wire. Defaults to False.
|
||||
|
||||
Returns:
|
||||
str: Verilog code for wire assignment.
|
||||
"""
|
||||
if array is True:
|
||||
return f" assign {self.name} = {name}[{offset}];\n"
|
||||
else:
|
||||
@ -34,15 +89,37 @@ class Wire():
|
||||
|
||||
""" BLIF CODE GENERATION """
|
||||
def get_declaration_blif(self, name: str = "", offset: int = 0, array: bool = False):
|
||||
"""Wire declaration in Blif code.
|
||||
|
||||
Declares basic wire name if wire is not a part of a bus,
|
||||
or declares wire by an offset of its position within the input bus.
|
||||
|
||||
Args:
|
||||
name (str, optional): Name of a bus to be declared (if array is True). Defaults to "".
|
||||
offset (int, optional): Offset wire location within a bus. Defaults to 0.
|
||||
array (bool, optional): Tells whether a basic wire or a wire from within a bus is to be declared. Defaults to False.
|
||||
|
||||
Returns:
|
||||
str: Blif code for declaration of a wire.
|
||||
"""
|
||||
if array is True:
|
||||
return f" {name}[{offset}]"
|
||||
else:
|
||||
return f" {self.name}"
|
||||
|
||||
def get_assign_blif(self, name: str, output: bool = False):
|
||||
"""Assignment of wire value to another desired wire in Blif.
|
||||
|
||||
Args:
|
||||
name (str): Name of the source/destination wire to be assigned to.
|
||||
output (bool, optional): Whether 'name' represents the destination or the source wire in the assignment. Defaults to False.
|
||||
|
||||
Returns:
|
||||
str: Blif code for assignment of one wire to another.
|
||||
"""
|
||||
if output is True:
|
||||
return f".names {self.name} {name}\n" + \
|
||||
f"1 1\n"
|
||||
else:
|
||||
return f".names {name} {self.name}\n" + \
|
||||
f"1 1\n"
|
||||
f"1 1\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user