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:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- 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'
@ -44,14 +44,17 @@ jobs:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Install iverilog
run: sudo apt install iverilog
- 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
- name: Download workflow run artifacts
uses: actions/download-artifact@v2
uses: actions/download-artifact@v3
with:
name: arithmetic-circuits-8
path: test_circuits
@ -84,12 +87,12 @@ jobs:
needs: build
strategy:
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
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Setup python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: x64
@ -104,9 +107,9 @@ jobs:
needs: test
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- 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'
@ -120,12 +123,12 @@ jobs:
- name: Generate documentation
run: pdoc --html ariths_gen
- name: Upload results
uses: actions/upload-artifact@v1.0.0
uses: actions/upload-artifact@v3
with:
name: documentation
path: html
- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@4.1.4
uses: JamesIves/github-pages-deploy-action@4
with:
branch: gh-pages # The branch the action should deploy to.
folder: html/ariths_gen # The folder the action should deploy.

View File

@ -46,6 +46,11 @@ class GeneralCircuit():
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):
"""Adds a component into list of circuit's inner subcomponents.

View File

@ -76,6 +76,12 @@ class Bus():
Wire: Returning wire from the bus.
"""
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
def connect(self, bus_wire_index: int, inner_component_out_wire: Wire, inserted_wire_desired_index: int = -1):
@ -100,6 +106,9 @@ class Bus():
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)
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):
"""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
# 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)]
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):
"""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:
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:
return ""
def __str__(self):
return f"<wire N={self.N} prefix={self.prefix} \"" + (",".join([str(w) for w in self.bus])) + "\">"
""" C CODE GENERATION """
def get_declaration_c(self):
"""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.
"""
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)
# 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():
return f"(({self.prefix} >> {self.index}) & 0x01) << {offset}\n"
return f"((({self.prefix} >> {self.index}) & 0x01) << {offset})\n"
else:
return f"(({self.name} >> 0) & 0x01) << {offset}\n"
return f"((({self.name} >> 0) & 0x01) << {offset})\n"
""" C CODE GENERATION """
def get_declaration_c(self):
@ -246,6 +247,13 @@ class Wire():
else:
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 #
class ConstantWireValue0(Wire):
@ -281,6 +289,7 @@ class ConstantWireValue0(Wire):
return True
class ConstantWireValue1(Wire):
"""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.
"""
return True

View File

@ -35,6 +35,16 @@ from ariths_gen.multi_bit_circuits.approximate_multipliers import (
UnsignedBrokenArrayMultiplier,
UnsignedBrokenCarrySaveMultiplier
)
from ariths_gen.one_bit_circuits.logic_gates import (
AndGate,
NandGate,
OrGate,
NorGate,
XorGate,
XnorGate,
NotGate
)
import numpy as np
@ -163,4 +173,33 @@ def test_mac():
r = mymac(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)