diff --git a/.github/workflows/generate.yml b/.github/workflows/generate.yml index 30d1a76..0d65701 100644 --- a/.github/workflows/generate.yml +++ b/.github/workflows/generate.yml @@ -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. \ No newline at end of file diff --git a/ariths_gen/core/arithmetic_circuits/general_circuit.py b/ariths_gen/core/arithmetic_circuits/general_circuit.py index aabd64a..0d73e03 100644 --- a/ariths_gen/core/arithmetic_circuits/general_circuit.py +++ b/ariths_gen/core/arithmetic_circuits/general_circuit.py @@ -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. diff --git a/ariths_gen/wire_components/buses.py b/ariths_gen/wire_components/buses.py index 5128f58..da97b38 100644 --- a/ariths_gen/wire_components/buses.py +++ b/ariths_gen/wire_components/buses.py @@ -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"" + """ C CODE GENERATION """ def get_declaration_c(self): """Bus declaration in C code. diff --git a/ariths_gen/wire_components/wires.py b/ariths_gen/wire_components/wires.py index 645674c..b397d00 100644 --- a/ariths_gen/wire_components/wires.py +++ b/ariths_gen/wire_components/wires.py @@ -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"" + elif self.is_buswire(): + return f"" + else: + return f"" # 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 + diff --git a/tests/test_all.py b/tests/test_all.py index 5bb9f46..7c0fd81 100644 --- a/tests/test_all.py +++ b/tests/test_all.py @@ -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) \ No newline at end of file + 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) \ No newline at end of file