Merge pull request #17 from ehw-fit/devel

This commit is contained in:
Jan Klhůfek 2023-02-22 18:59:31 +01:00 committed by GitHub
commit 2d7e157453
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 18 deletions

View File

@ -17,9 +17,9 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Set up Python 3.x - name: Set up Python 3.x
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
# Semantic version range syntax or exact version of a Python version # Semantic version range syntax or exact version of a Python version
python-version: '3.x' python-version: '3.x'
@ -44,14 +44,17 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Install iverilog - name: Install iverilog
run: sudo apt install iverilog run: sudo apt install iverilog
- name: Set up Python 3.x - name: Set up Python 3.x
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with:
# Semantic version range syntax or exact version of a Python version
python-version: '3.x'
- run: python -m pip install numpy - run: python -m pip install numpy
- name: Download workflow run artifacts - name: Download workflow run artifacts
uses: actions/download-artifact@v2 uses: actions/download-artifact@v3
with: with:
name: arithmetic-circuits-8 name: arithmetic-circuits-8
path: test_circuits path: test_circuits
@ -84,12 +87,12 @@ jobs:
needs: build needs: build
strategy: strategy:
matrix: matrix:
python-version: [ '3.6.x', '3.7.x', '3.8.x', '3.9.x', '3.10.0-rc.2' ] python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11' ]
name: Python ${{ matrix.python-version }} test name: Python ${{ matrix.python-version }} test
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Setup python - name: Setup python
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
architecture: x64 architecture: x64
@ -104,9 +107,9 @@ jobs:
needs: test needs: test
if: github.ref == 'refs/heads/main' if: github.ref == 'refs/heads/main'
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Set up Python 3.x - name: Set up Python 3.x
uses: actions/setup-python@v2 uses: actions/setup-python@v4
with: with:
# Semantic version range syntax or exact version of a Python version # Semantic version range syntax or exact version of a Python version
python-version: '3.x' python-version: '3.x'
@ -120,12 +123,12 @@ jobs:
- name: Generate documentation - name: Generate documentation
run: pdoc --html ariths_gen run: pdoc --html ariths_gen
- name: Upload results - name: Upload results
uses: actions/upload-artifact@v1.0.0 uses: actions/upload-artifact@v3
with: with:
name: documentation name: documentation
path: html path: html
- name: Deploy 🚀 - name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.1.4 uses: JamesIves/github-pages-deploy-action@4
with: with:
branch: gh-pages # The branch the action should deploy to. branch: gh-pages # The branch the action should deploy to.
folder: html/ariths_gen # The folder the action should deploy. folder: html/ariths_gen # The folder the action should deploy.

View File

@ -46,6 +46,11 @@ class GeneralCircuit():
return self.pyc(*args) return self.pyc(*args)
def __str__(self):
return f"<{type(self).__name__} prefix={self.prefix} " + (", ".join([f"input={i}" for i in self.inputs])) + ">"
#super().__init__(prefix, name, out_N, inner_component, inputs=[a, b], signed=signed, **kwargs)
def add_component(self, component): def add_component(self, component):
"""Adds a component into list of circuit's inner subcomponents. """Adds a component into list of circuit's inner subcomponents.

View File

@ -77,6 +77,12 @@ class Bus():
""" """
return self.bus[wire_index] return self.bus[wire_index]
def __getitem__(self, i):
return self.bus[i]
def __getitem__(self, i):
return self.get_wire(i)
# Connecting output wire of the inner circuit component to desired position in the described circuit's output bus # Connecting output wire of the inner circuit component to desired position in the described circuit's output bus
def connect(self, bus_wire_index: int, inner_component_out_wire: Wire, inserted_wire_desired_index: int = -1): def connect(self, bus_wire_index: int, inner_component_out_wire: Wire, inserted_wire_desired_index: int = -1):
"""Connects given 'Wire' object to a 'bus_wire_index' within this bus. """Connects given 'Wire' object to a 'bus_wire_index' within this bus.
@ -100,6 +106,9 @@ class Bus():
elif inserted_wire_desired_index != -1: elif inserted_wire_desired_index != -1:
self.bus[bus_wire_index] = Wire(name=inner_component_out_wire.name, prefix=inner_component_out_wire.parent_bus.prefix, index=inserted_wire_index, value=inner_component_out_wire.value, parent_bus=self) self.bus[bus_wire_index] = Wire(name=inner_component_out_wire.name, prefix=inner_component_out_wire.parent_bus.prefix, index=inserted_wire_index, value=inner_component_out_wire.value, parent_bus=self)
def __setitem__(self, i, v):
self.connect(i, v)
def connect_bus(self, connecting_bus: object, start_connection_pos: int = 0, end_connection_pos: int = -1, offset: int = 0): def connect_bus(self, connecting_bus: object, start_connection_pos: int = 0, end_connection_pos: int = -1, offset: int = 0):
"""Ensures connection of specified bus wires to this bus wires. """Ensures connection of specified bus wires to this bus wires.
@ -127,7 +136,7 @@ class Bus():
# Ensures correct binding between the bus wire index and the wire itself # Ensures correct binding between the bus wire index and the wire itself
# It is used for the case when multiple of the same wire (e.g. `ContantWireValue0()`) are present in the bus (its id would otherwise be incorrect when using `self.bus.index(_)`) # It is used for the case when multiple of the same wire (e.g. `ContantWireValue0()`) are present in the bus (its id would otherwise be incorrect when using `self.bus.index(_)`)
mapped_positions = [(w_id, self.bus[w_id]) for w_id in range(self.N)] mapped_positions = [(w_id, self.bus[w_id]) for w_id in range(self.N)]
return "".join([f" {self.prefix} = 0\n"] + [f" {self.prefix} |= {w[1].return_wire_value_python_flat(offset=w[0])}" for w in mapped_positions]) return "".join([f" {self.prefix} = 0\n"] + [f" {self.prefix} = ({self.prefix}) | {w[1].return_wire_value_python_flat(offset=w[0])}" for w in mapped_positions])
def return_bus_wires_sign_extend_python_flat(self): def return_bus_wires_sign_extend_python_flat(self):
"""Sign extends the bus's corresponding Python variable (object) to ensure proper flat Python code variable signedness. """Sign extends the bus's corresponding Python variable (object) to ensure proper flat Python code variable signedness.
@ -137,10 +146,13 @@ class Bus():
""" """
if self.signed is True: if self.signed is True:
last_bus_wire = self.bus[-1] last_bus_wire = self.bus[-1]
return "".join([f" {self.prefix} |= {last_bus_wire.return_wire_value_python_flat(offset=i)}" for i in range(len(self.bus), 64)]) return "".join([f" {self.prefix} = ({self.prefix}) | {last_bus_wire.return_wire_value_python_flat(offset=i)}" for i in range(len(self.bus), 64)])
else: else:
return "" return ""
def __str__(self):
return f"<wire N={self.N} prefix={self.prefix} \"" + (",".join([str(w) for w in self.bus])) + "\">"
""" C CODE GENERATION """ """ C CODE GENERATION """
def get_declaration_c(self): def get_declaration_c(self):
"""Bus declaration in C code. """Bus declaration in C code.

View File

@ -40,13 +40,14 @@ class Wire():
str: Python code bitwise shift for storing (constant/variable) wire value at desired offset position. str: Python code bitwise shift for storing (constant/variable) wire value at desired offset position.
""" """
if self.is_const(): if self.is_const():
return f"({self.c_const}) << {offset}\n" return f"(({self.c_const}) << {offset})\n"
# If wire is part of an input bus (where wire names are concatenated from bus prefix and their index position inside the bus in square brackets) # If wire is part of an input bus (where wire names are concatenated from bus prefix and their index position inside the bus in square brackets)
# then the wire value is obtained from bitwise shifting the required wire from the parent bus ('parent_bus.prefix' is the same value as 'self.prefix') # then the wire value is obtained from bitwise shifting the required wire from the parent bus ('parent_bus.prefix' is the same value as 'self.prefix')
elif self.is_buswire(): elif self.is_buswire():
return f"(({self.prefix} >> {self.index}) & 0x01) << {offset}\n" return f"((({self.prefix} >> {self.index}) & 0x01) << {offset})\n"
else: else:
return f"(({self.name} >> 0) & 0x01) << {offset}\n" return f"((({self.name} >> 0) & 0x01) << {offset})\n"
""" C CODE GENERATION """ """ C CODE GENERATION """
def get_declaration_c(self): def get_declaration_c(self):
@ -246,6 +247,13 @@ class Wire():
else: else:
return self.prefix return self.prefix
def __str__(self):
if self.is_const():
return f"<w={self.c_const}>"
elif self.is_buswire():
return f"<w={self.prefix}[{self.index}]>"
else:
return f"<w={self.name}>"
# Wires with constant values # # Wires with constant values #
class ConstantWireValue0(Wire): class ConstantWireValue0(Wire):
@ -281,6 +289,7 @@ class ConstantWireValue0(Wire):
return True return True
class ConstantWireValue1(Wire): class ConstantWireValue1(Wire):
"""Class representing wire carrying constant value 1 used to interconnect components. """Class representing wire carrying constant value 1 used to interconnect components.
@ -312,3 +321,4 @@ class ConstantWireValue1(Wire):
bool: True, because constant wire carries a constant value 1. bool: True, because constant wire carries a constant value 1.
""" """
return True return True

View File

@ -35,6 +35,16 @@ from ariths_gen.multi_bit_circuits.approximate_multipliers import (
UnsignedBrokenArrayMultiplier, UnsignedBrokenArrayMultiplier,
UnsignedBrokenCarrySaveMultiplier UnsignedBrokenCarrySaveMultiplier
) )
from ariths_gen.one_bit_circuits.logic_gates import (
AndGate,
NandGate,
OrGate,
NorGate,
XorGate,
XnorGate,
NotGate
)
import numpy as np import numpy as np
@ -164,3 +174,32 @@ def test_mac():
r = mymac(av, bv, cv) r = mymac(av, bv, cv)
expected = (av * bv) + cv expected = (av * bv) + cv
np.testing.assert_array_equal(r, expected) np.testing.assert_array_equal(r, expected)
def test_direct():
class err_circuit(GeneralCircuit):
def __init__(self, prefix: str = "", name: str = "adder", inner_component: bool = True, a: Bus = Bus(), b: Bus = Bus()):
super().__init__(prefix = prefix, name=name, out_N = (a.N + 1), inner_component=inner_component, inputs = [a, b])
self.N = 1
self.prefix = prefix
self.a = Bus(prefix=a.prefix, wires_list=a.bus)
self.b = Bus(prefix=b.prefix, wires_list=b.bus)
self.out = Bus(self.prefix+"_out", self.N+1)
a_0 = self.a[0]
b_0 = self.b.get_wire(0)
or_1 = OrGate(a_0, b_0, prefix=self.prefix+"_or"+str(self.get_instance_num(cls=OrGate)), parent_component=self)
self.add_component(or_1)
self.out.connect(0, a_0)
self.out.connect(1, or_1.out)
av = np.arange(0, 4).reshape(1, -1)
bv = np.arange(0, 4).reshape(-1, 1)
example = err_circuit(prefix = "err_circuit", a = Bus("a", 2) , b = Bus("b", 2))
r = example(av, bv)
expected = np.array([[0, 3, 0, 3], [2, 3 ,2, 3], [0, 3, 0, 3], [2, 3, 2, 3]])
np.testing.assert_equal(r, expected)
print(r)