Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • da/B-ASIC
  • lukja239/B-ASIC
  • robal695/B-ASIC
3 results
Show changes
Commits on Source (6)
Showing
with 152 additions and 119 deletions
...@@ -85,6 +85,12 @@ run-test-3.11-pyqt5: ...@@ -85,6 +85,12 @@ run-test-3.11-pyqt5:
image: python:3.11 image: python:3.11
extends: ".run-test" extends: ".run-test"
run-test-3.12-pyqt5:
variables:
QT_API: pyqt5
image: python:3.12
extends: ".run-test"
# Seemingly works with Qt6, but tests stall on closing scheduler GUI due to modal dialog(?) # Seemingly works with Qt6, but tests stall on closing scheduler GUI due to modal dialog(?)
#run-test-3.10-pyside6: #run-test-3.10-pyside6:
# variables: # variables:
...@@ -124,7 +130,7 @@ run-doc-test: ...@@ -124,7 +130,7 @@ run-doc-test:
- pip install black velin - pip install black velin
- velin . --check --black - velin . --check --black
- pip install ruff - pip install ruff
- ruff b_asic --format=gitlab > ruff.json - ruff b_asic --output-format=gitlab > ruff.json
artifacts: artifacts:
name: "${CI_PROJECT_NAME}_code_quality" name: "${CI_PROJECT_NAME}_code_quality"
when: always when: always
......
repos: repos:
- repo: https://github.com/pre-commit/pre-commit-hooks - repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0 rev: v4.6.0
hooks: hooks:
- id: mixed-line-ending - id: mixed-line-ending
exclude_types: [svg] exclude_types: [svg]
...@@ -13,13 +13,18 @@ repos: ...@@ -13,13 +13,18 @@ repos:
exclude_types: [svg] exclude_types: [svg]
- id: check-toml - id: check-toml
- repo: https://github.com/crate-ci/typos
rev: v1.20.7
hooks:
- id: typos
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 23.3.0 rev: 24.3.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/pycqa/isort - repo: https://github.com/pycqa/isort
rev: 5.12.0 rev: 5.13.2
hooks: hooks:
- id: isort - id: isort
name: isort (python) name: isort (python)
...@@ -31,23 +36,23 @@ repos: ...@@ -31,23 +36,23 @@ repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit - repo: https://github.com/charliermarsh/ruff-pre-commit
# Ruff version. # Ruff version.
rev: "v0.0.267" rev: "v0.3.5"
hooks: hooks:
- id: ruff - id: ruff
- repo: https://github.com/adamchainz/blacken-docs - repo: https://github.com/adamchainz/blacken-docs
rev: 1.13.0 rev: 1.16.0
hooks: hooks:
- id: blacken-docs - id: blacken-docs
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v3.4.0 rev: v3.15.2
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py38-plus] args: [--py38-plus]
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.0.0-alpha.9-for-vscode rev: v4.0.0-alpha.8
hooks: hooks:
- id: prettier - id: prettier
files: \.(html|md|yml|yaml|toml) files: \.(html|md|yml|yaml|toml)
......
...@@ -14,46 +14,46 @@ How to build and debug the library during development. ...@@ -14,46 +14,46 @@ How to build and debug the library during development.
The following packages are required in order to build the library: The following packages are required in order to build the library:
- [Python](https://python.org/) 3.8+ - [Python](https://python.org/) 3.8+
- Python dependencies (install with `pip install -r requirements.txt` or they will be installed as part of the - Python dependencies (install with `pip install -r requirements.txt` or they will be installed as part of the
installation process): installation process):
- [Graphviz](https://graphviz.org/) - [Graphviz](https://graphviz.org/)
- [Matplotlib](https://matplotlib.org/) - [Matplotlib](https://matplotlib.org/)
- [NumPy](https://numpy.org/) - [NumPy](https://numpy.org/)
- [QtPy](https://github.com/spyder-ide/qtpy) - [QtPy](https://github.com/spyder-ide/qtpy)
- [setuptools_scm](https://github.com/pypa/setuptools_scm/) - [setuptools_scm](https://github.com/pypa/setuptools_scm/)
- [NetworkX](https://networkx.org/) - [NetworkX](https://networkx.org/)
- [QtAwesome](https://github.com/spyder-ide/qtawesome/) - [QtAwesome](https://github.com/spyder-ide/qtawesome/)
- Qt 5 or 6, with Python bindings, one of: - Qt 5 or 6, with Python bindings, one of:
- pyside2 - pyside2
- pyqt5 - pyqt5
- pyside6 - pyside6
- pyqt6 - pyqt6
To build a binary distribution, the following additional packages are required: To build a binary distribution, the following additional packages are required:
- Python: - Python:
- wheel - wheel
To run the test suite, the following additional packages are required: To run the test suite, the following additional packages are required:
- Python (install with `pip install -r requirements_test.txt`): - Python (install with `pip install -r requirements_test.txt`):
- [pytest](https://pytest.org/) - [pytest](https://pytest.org/)
- [pytest-qt](https://pytest-qt.readthedocs.io/) - [pytest-qt](https://pytest-qt.readthedocs.io/)
- [pytest-mpl](https://github.com/matplotlib/pytest-mpl/) - [pytest-mpl](https://github.com/matplotlib/pytest-mpl/)
- [pytest-cov](https://pytest-cov.readthedocs.io/en/latest/) (for testing with coverage) - [pytest-cov](https://pytest-cov.readthedocs.io/en/latest/) (for testing with coverage)
- [pytest-xvfb](https://github.com/The-Compiler/pytest-xvfb) (for testing without showing windows on Linux, you will also need to install [xvfb](https://www.x.org/releases/X11R7.6/doc/man/man1/Xvfb.1.xhtml)) - [pytest-xvfb](https://github.com/The-Compiler/pytest-xvfb) (for testing without showing windows on Linux, you will also need to install [xvfb](https://www.x.org/releases/X11R7.6/doc/man/man1/Xvfb.1.xhtml))
- [pytest-xdist](https://pytest-xdist.readthedocs.io/) (for parallel testing) - [pytest-xdist](https://pytest-xdist.readthedocs.io/) (for parallel testing)
To generate the documentation, the following additional packages are required: To generate the documentation, the following additional packages are required:
- Python (install with `pip install -r requirements_doc.txt`): - Python (install with `pip install -r requirements_doc.txt`):
- [Sphinx](https://www.sphinx-doc.org/) - [Sphinx](https://www.sphinx-doc.org/)
- [Furo](https://pradyunsg.me/furo/) - [Furo](https://pradyunsg.me/furo/)
- [numpydoc](https://numpydoc.readthedocs.io/) - [numpydoc](https://numpydoc.readthedocs.io/)
- [Sphinx-Gallery](https://sphinx-gallery.github.io/) - [Sphinx-Gallery](https://sphinx-gallery.github.io/)
- [mplsignal](https://mplsignal.readthedocs.io/) - [mplsignal](https://mplsignal.readthedocs.io/)
- [sphinx-copybutton](https://sphinx-copybutton.readthedocs.io/) - [sphinx-copybutton](https://sphinx-copybutton.readthedocs.io/)
### Using setuptools to create a package ### Using setuptools to create a package
...@@ -63,7 +63,7 @@ How to create a package using setuptools that can be installed using pip. ...@@ -63,7 +63,7 @@ How to create a package using setuptools that can be installed using pip.
In `B-ASIC`: In `B-ASIC`:
``` ```bash
python3 setup.py bdist_wheel python3 setup.py bdist_wheel
``` ```
...@@ -73,7 +73,7 @@ The output gets written to `B-ASIC/dist/b_asic-<version>-<python_tag>-<abi_tag>- ...@@ -73,7 +73,7 @@ The output gets written to `B-ASIC/dist/b_asic-<version>-<python_tag>-<abi_tag>-
In `B-ASIC`: In `B-ASIC`:
``` ```bash
python3 setup.py sdist python3 setup.py sdist
``` ```
...@@ -83,7 +83,7 @@ The output gets written to `B-ASIC/dist/b-asic-<version>.tar.gz`. ...@@ -83,7 +83,7 @@ The output gets written to `B-ASIC/dist/b-asic-<version>.tar.gz`.
In `B-ASIC/dist`: In `B-ASIC/dist`:
``` ```bash
pip install b_asic-<version>-<python_tag>-<abi_tag>-<platform_tag>.whl pip install b_asic-<version>-<python_tag>-<abi_tag>-<platform_tag>.whl
``` ```
...@@ -91,7 +91,7 @@ pip install b_asic-<version>-<python_tag>-<abi_tag>-<platform_tag>.whl ...@@ -91,7 +91,7 @@ pip install b_asic-<version>-<python_tag>-<abi_tag>-<platform_tag>.whl
In `B-ASIC/dist`: In `B-ASIC/dist`:
``` ```bash
pip install b-asic-<version>.tar.gz pip install b-asic-<version>.tar.gz
``` ```
...@@ -103,7 +103,7 @@ How to run the tests using pytest in a virtual environment. ...@@ -103,7 +103,7 @@ How to run the tests using pytest in a virtual environment.
In `B-ASIC`: In `B-ASIC`:
``` ```bash
python3 -m venv env python3 -m venv env
source env/bin/activate source env/bin/activate
pip install . pip install .
...@@ -114,7 +114,7 @@ pytest ...@@ -114,7 +114,7 @@ pytest
In `B-ASIC` (as admin): In `B-ASIC` (as admin):
``` ```bash
python3 -m venv env python3 -m venv env
.\env\Scripts\activate.bat .\env\Scripts\activate.bat
pip install . pip install .
...@@ -123,7 +123,7 @@ pytest ...@@ -123,7 +123,7 @@ pytest
#### Test with coverage #### Test with coverage
``` ```bash
pytest --cov=b_asic --cov-report=html test pytest --cov=b_asic --cov-report=html test
``` ```
...@@ -131,18 +131,20 @@ pytest --cov=b_asic --cov-report=html test ...@@ -131,18 +131,20 @@ pytest --cov=b_asic --cov-report=html test
In `B-ASIC`: In `B-ASIC`:
``` ```bash
pytest # The image comparison tests will fail pytest # The image comparison tests will fail
cp -a result_images/* test/baseline_images/ cp -a result_images/* test/baseline_images/
``` ```
### Generating documentation ### Generating documentation
``` ```bash
sphinx-build -b html docs_sphinx docs_sphinx/_build sphinx-build -b html docs_sphinx docs_sphinx/_build
``` ```
or in `B-ASIC/docs_sphinx`: or in `B-ASIC/docs_sphinx`:
```
```bash
make html make html
``` ```
...@@ -154,13 +156,13 @@ How to build and use the library as a user. ...@@ -154,13 +156,13 @@ How to build and use the library as a user.
### Installation ### Installation
``` ```bash
pip install . pip install .
``` ```
### Importing ### Importing
``` ```bash
python3 python3
>>> import b_asic as asic >>> import b_asic as asic
>>> help(asic) >>> help(asic)
......
...@@ -101,7 +101,7 @@ class Arrow(QGraphicsPathItem): ...@@ -101,7 +101,7 @@ class Arrow(QGraphicsPathItem):
return cast("OutputPort", self._source_port_button.port) return cast("OutputPort", self._source_port_button.port)
@property @property
def desination_port(self) -> "InputPort": def destination_port(self) -> "InputPort":
"""The destination InputPort.""" """The destination InputPort."""
return cast("InputPort", self._destination_port_button.port) return cast("InputPort", self._destination_port_button.port)
......
# -*- coding: utf-8 -*-
# Originally generated from QT designer, but now manually maintained # Originally generated from QT designer, but now manually maintained
from qtpy import QtCore, QtWidgets from qtpy import QtCore, QtWidgets
class Ui_main_window(object): class Ui_main_window:
def setupUi(self, main_window): def setupUi(self, main_window):
main_window.setObjectName("main_window") main_window.setObjectName("main_window")
main_window.setEnabled(True) main_window.setEnabled(True)
......
...@@ -4,7 +4,6 @@ B-ASIC Signal Flow Graph Editor Module. ...@@ -4,7 +4,6 @@ B-ASIC Signal Flow Graph Editor Module.
This file opens the main SFG editor window of the GUI for B-ASIC when run. This file opens the main SFG editor window of the GUI for B-ASIC when run.
""" """
import importlib.util import importlib.util
import logging import logging
import os import os
...@@ -814,8 +813,8 @@ class SFGMainWindow(QMainWindow): ...@@ -814,8 +813,8 @@ class SFGMainWindow(QMainWindow):
raise ValueError("Exactly one output port must be selected!") raise ValueError("Exactly one output port must be selected!")
pressed_op_outport = pressed_op_outports[0] pressed_op_outport = pressed_op_outports[0]
for pressed_op_inport in pressed_op_inports: for pressed_op_input_port in pressed_op_inports:
self._connect_button(pressed_op_outport, pressed_op_inport) self._connect_button(pressed_op_outport, pressed_op_input_port)
for port in self._pressed_ports: for port in self._pressed_ports:
port.select_port() port.select_port()
...@@ -979,6 +978,7 @@ def start_editor(sfg: Optional[SFG] = None) -> Dict[str, SFG]: ...@@ -979,6 +978,7 @@ def start_editor(sfg: Optional[SFG] = None) -> Dict[str, SFG]:
All SFGs currently in the editor. All SFGs currently in the editor.
""" """
if not QApplication.instance(): if not QApplication.instance():
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(sys.argv) app = QApplication(sys.argv)
else: else:
app = QApplication.instance() app = QApplication.instance()
......
""" """
B-ASIC architecture classes. B-ASIC architecture classes.
""" """
from collections import defaultdict from collections import defaultdict
from io import TextIOWrapper from io import TextIOWrapper
from itertools import chain from itertools import chain
...@@ -588,13 +589,13 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -588,13 +589,13 @@ of :class:`~b_asic.architecture.ProcessingElement`
) )
self._memories = [memories] if isinstance(memories, Memory) else list(memories) self._memories = [memories] if isinstance(memories, Memory) else list(memories)
self._direct_interconnects = direct_interconnects self._direct_interconnects = direct_interconnects
self._variable_inport_to_resource: DefaultDict[ self._variable_input_port_to_resource: DefaultDict[
InputPort, Set[Tuple[Resource, int]] InputPort, Set[Tuple[Resource, int]]
] = defaultdict(set) ] = defaultdict(set)
self._variable_outport_to_resource: DefaultDict[ self._variable_outport_to_resource: DefaultDict[
OutputPort, Set[Tuple[Resource, int]] OutputPort, Set[Tuple[Resource, int]]
] = defaultdict(set) ] = defaultdict(set)
self._operation_inport_to_resource: Dict[InputPort, Resource] = {} self._operation_input_port_to_resource: Dict[InputPort, Resource] = {}
self._operation_outport_to_resource: Dict[OutputPort, Resource] = {} self._operation_outport_to_resource: Dict[OutputPort, Resource] = {}
self._schedule_time = self._check_and_get_schedule_time() self._schedule_time = self._check_and_get_schedule_time()
...@@ -617,25 +618,27 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -617,25 +618,27 @@ of :class:`~b_asic.architecture.ProcessingElement`
return schedule_times.pop() return schedule_times.pop()
def _build_dicts(self) -> None: def _build_dicts(self) -> None:
self._variable_inport_to_resource: DefaultDict[ self._variable_input_port_to_resource: DefaultDict[
InputPort, Set[Tuple[Resource, int]] InputPort, Set[Tuple[Resource, int]]
] = defaultdict(set) ] = defaultdict(set)
self._variable_outport_to_resource: DefaultDict[ self._variable_outport_to_resource: DefaultDict[
OutputPort, Set[Tuple[Resource, int]] OutputPort, Set[Tuple[Resource, int]]
] = defaultdict(set) ] = defaultdict(set)
self._operation_inport_to_resource = {} self._operation_input_port_to_resource = {}
self._operation_outport_to_resource = {} self._operation_outport_to_resource = {}
for pe in self.processing_elements: for pe in self.processing_elements:
for operator in pe.processes: for operator in pe.processes:
for input_port in operator.operation.inputs: for input_port in operator.operation.inputs:
self._operation_inport_to_resource[input_port] = pe self._operation_input_port_to_resource[input_port] = pe
for output_port in operator.operation.outputs: for output_port in operator.operation.outputs:
self._operation_outport_to_resource[output_port] = pe self._operation_outport_to_resource[output_port] = pe
for memory in self.memories: for memory in self.memories:
for mv in memory: for mv in memory:
for read_port in mv.read_ports: for read_port in mv.read_ports:
self._variable_inport_to_resource[read_port].add((memory, 0)) # Fix self._variable_input_port_to_resource[read_port].add(
(memory, 0)
) # Fix
self._variable_outport_to_resource[mv.write_port].add( self._variable_outport_to_resource[mv.write_port].add(
(memory, 0) (memory, 0)
) # Fix ) # Fix
...@@ -643,7 +646,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -643,7 +646,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
for di in self._direct_interconnects: for di in self._direct_interconnects:
di = cast(MemoryVariable, di) di = cast(MemoryVariable, di)
for read_port in di.read_ports: for read_port in di.read_ports:
self._variable_inport_to_resource[read_port].add( self._variable_input_port_to_resource[read_port].add(
( (
self._operation_outport_to_resource[di.write_port], self._operation_outport_to_resource[di.write_port],
di.write_port.index, di.write_port.index,
...@@ -651,7 +654,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -651,7 +654,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
) )
self._variable_outport_to_resource[di.write_port].add( self._variable_outport_to_resource[di.write_port].add(
( (
self._operation_inport_to_resource[read_port], self._operation_input_port_to_resource[read_port],
read_port.index, read_port.index,
) )
) )
...@@ -718,7 +721,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -718,7 +721,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
var = cast(MemoryVariable, var) var = cast(MemoryVariable, var)
d_in[self._operation_outport_to_resource[var.write_port]] += 1 d_in[self._operation_outport_to_resource[var.write_port]] += 1
for read_port in var.read_ports: for read_port in var.read_ports:
d_out[self._operation_inport_to_resource[read_port]] += 1 d_out[self._operation_input_port_to_resource[read_port]] += 1
return dict(d_in), dict(d_out) return dict(d_in), dict(d_out)
def get_interconnects_for_pe( def get_interconnects_for_pe(
...@@ -739,7 +742,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -739,7 +742,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
Returns Returns
------- -------
list list
List of dictionaries indicating the sources for each inport and the List of dictionaries indicating the sources for each import and the
frequency of accesses. frequency of accesses.
list list
List of dictionaries indicating the sources for each outport and the List of dictionaries indicating the sources for each outport and the
...@@ -757,7 +760,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -757,7 +760,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
for var in pe.collection: for var in pe.collection:
var = cast(OperatorProcess, var) var = cast(OperatorProcess, var)
for i, input_ in enumerate(var.operation.inputs): for i, input_ in enumerate(var.operation.inputs):
for v in self._variable_inport_to_resource[input_]: for v in self._variable_input_port_to_resource[input_]:
d_in[i][v] += 1 d_in[i][v] += 1
for i, output in enumerate(var.operation.outputs): for i, output in enumerate(var.operation.outputs):
for v in self._variable_outport_to_resource[output]: for v in self._variable_outport_to_resource[output]:
......
""" """
Module for code generation of VHDL architectures. Module for code generation of VHDL architectures.
""" """
from math import ceil, log2 from math import ceil, log2
from typing import TYPE_CHECKING, Dict, List, Optional, Set, TextIO, Tuple, cast from typing import TYPE_CHECKING, Dict, List, Optional, Set, TextIO, Tuple, cast
...@@ -320,7 +321,7 @@ def memory_based_storage( ...@@ -320,7 +321,7 @@ def memory_based_storage(
for mv in collection: for mv in collection:
mv = cast(MemoryVariable, mv) mv = cast(MemoryVariable, mv)
if mv.start_time >= schedule_time: if mv.start_time >= schedule_time:
raise ValueError('start_time greater than scheudle_time') raise ValueError('start_time greater than schedule_time')
if mv.execution_time: if mv.execution_time:
write_list[mv.start_time] = (i, mv) write_list[mv.start_time] = (i, mv)
......
...@@ -162,7 +162,7 @@ def constant_declaration( ...@@ -162,7 +162,7 @@ def constant_declaration(
Signal name. Signal name.
signal_type : str signal_type : str
Signal type. Signal type.
value : anything convertable to str value : anything convertible to str
Default value to the signal. Default value to the signal.
name_pad : int, optional name_pad : int, optional
An optional left padding value applied to the name. An optional left padding value applied to the name.
......
...@@ -251,6 +251,7 @@ def start_simulation_dialog( ...@@ -251,6 +251,7 @@ def start_simulation_dialog(
The name of the SFG. The name of the SFG.
""" """
if not QApplication.instance(): if not QApplication.instance():
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(sys.argv) app = QApplication(sys.argv)
else: else:
app = QApplication.instance() app = QApplication.instance()
......
...@@ -552,12 +552,12 @@ class AbstractOperation(Operation, AbstractGraphComponent): ...@@ -552,12 +552,12 @@ class AbstractOperation(Operation, AbstractGraphComponent):
def __str__(self) -> str: def __str__(self) -> str:
"""Get a string representation of this operation.""" """Get a string representation of this operation."""
inputs_dict: Dict[int, Union[List[GraphID], str]] = {} inputs_dict: Dict[int, Union[List[GraphID], str]] = {}
for i, inport in enumerate(self.inputs): for i, current_input in enumerate(self.inputs):
if inport.signal_count == 0: if current_input.signal_count == 0:
inputs_dict[i] = "-" inputs_dict[i] = "-"
break break
dict_ele = [] dict_ele = []
for signal in inport.signals: for signal in current_input.signals:
if signal.source: if signal.source:
if signal.source_operation.graph_id: if signal.source_operation.graph_id:
dict_ele.append(signal.source_operation.graph_id) dict_ele.append(signal.source_operation.graph_id)
...@@ -919,8 +919,8 @@ class AbstractOperation(Operation, AbstractGraphComponent): ...@@ -919,8 +919,8 @@ class AbstractOperation(Operation, AbstractGraphComponent):
def set_latency(self, latency: int) -> None: def set_latency(self, latency: int) -> None:
if latency < 0: if latency < 0:
raise ValueError("Latency cannot be negative") raise ValueError("Latency cannot be negative")
for inport in self.inputs: for current_input in self.inputs:
inport.latency_offset = 0 current_input.latency_offset = 0
for outport in self.outputs: for outport in self.outputs:
outport.latency_offset = latency outport.latency_offset = latency
......
...@@ -963,10 +963,10 @@ class ProcessCollection: ...@@ -963,10 +963,10 @@ class ProcessCollection:
Split this collection into multiple new collections by sequentially assigning Split this collection into multiple new collections by sequentially assigning
processes in the order of `sequence`. processes in the order of `sequence`.
This method takes the processes from `sequence`, in order, and assignes them to This method takes the processes from `sequence`, in order, and assigns them to
to multiple new `ProcessCollection` based on port collisions in a first-come to multiple new `ProcessCollection` based on port collisions in a first-come
first-served manner. The first `Process` in `sequence` is assigned first, and first-served manner. The first `Process` in `sequence` is assigned first, and
the last `Proccess` in `sequence is assigned last. the last `Process` in `sequence is assigned last.
Parameters Parameters
---------- ----------
...@@ -1369,7 +1369,7 @@ class ProcessCollection: ...@@ -1369,7 +1369,7 @@ class ProcessCollection:
raise ValueError('input_sync needs to be set to use address pipelining') raise ValueError('input_sync needs to be set to use address pipelining')
if not log2(adr_mux_size).is_integer(): if not log2(adr_mux_size).is_integer():
raise ValueError( raise ValueError(
f'adr_mux_size={adr_mux_size} needs to be interger power of two' f'adr_mux_size={adr_mux_size} needs to be integer power of two'
) )
if adr_mux_size**adr_pipe_depth > assignment[0].schedule_time: if adr_mux_size**adr_pipe_depth > assignment[0].schedule_time:
raise ValueError( raise ValueError(
......
...@@ -178,7 +178,7 @@ class Schedule: ...@@ -178,7 +178,7 @@ class Schedule:
Returns Returns
------- -------
int int
The number of time steps the operation with *graph_id* can ba moved The number of time steps the operation with *graph_id* can be moved
forward in time. forward in time.
See Also See Also
...@@ -243,7 +243,7 @@ class Schedule: ...@@ -243,7 +243,7 @@ class Schedule:
Returns Returns
------- -------
int int
The number of time steps the operation with *graph_id* can ba moved The number of time steps the operation with *graph_id* can be moved
backward in time. backward in time.
.. note:: The backward slack is positive, but a call to .. note:: The backward slack is positive, but a call to
:func:`move_operation` should be negative to move the operation :func:`move_operation` should be negative to move the operation
...@@ -723,7 +723,7 @@ class Schedule: ...@@ -723,7 +723,7 @@ class Schedule:
schedule.move_operation(graph_id, -schedule.backward_slack(graph_id)) schedule.move_operation(graph_id, -schedule.backward_slack(graph_id))
but operations that do not have a preceeding operation (Inputs and Constants) but operations that do not have a preceding operation (Inputs and Constants)
will only move to the start of the schedule. will only move to the start of the schedule.
Parameters Parameters
...@@ -825,16 +825,16 @@ class Schedule: ...@@ -825,16 +825,16 @@ class Schedule:
if operation.graph_id not in self._start_times: if operation.graph_id not in self._start_times:
# Schedule the operation if it does not have a start time yet. # Schedule the operation if it does not have a start time yet.
op_start_time = 0 op_start_time = 0
for inport in operation.inputs: for current_input in operation.inputs:
if len(inport.signals) != 1: if len(current_input.signals) != 1:
raise ValueError( raise ValueError(
"Error in scheduling, dangling input port detected." "Error in scheduling, dangling input port detected."
) )
if inport.signals[0].source is None: if current_input.signals[0].source is None:
raise ValueError( raise ValueError(
"Error in scheduling, signal with no source detected." "Error in scheduling, signal with no source detected."
) )
source_port = inport.signals[0].source source_port = current_input.signals[0].source
if source_port.operation.graph_id in non_schedulable_ops: if source_port.operation.graph_id in non_schedulable_ops:
source_end_time = 0 source_end_time = 0
...@@ -855,13 +855,15 @@ class Schedule: ...@@ -855,13 +855,15 @@ class Schedule:
source_op_time + source_port.latency_offset source_op_time + source_port.latency_offset
) )
if inport.latency_offset is None: if current_input.latency_offset is None:
raise ValueError( raise ValueError(
f"Input port {inport.index} of operation" f"Input port {current_input.index} of operation"
f" {inport.operation.graph_id} has no" f" {current_input.operation.graph_id} has no"
" latency-offset." " latency-offset."
) )
op_start_time_from_in = source_end_time - inport.latency_offset op_start_time_from_in = (
source_end_time - current_input.latency_offset
)
op_start_time = max(op_start_time, op_start_time_from_in) op_start_time = max(op_start_time, op_start_time_from_in)
self._start_times[operation.graph_id] = op_start_time self._start_times[operation.graph_id] = op_start_time
......
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
""" """
B-ASIC Scheduler-gui Logger Module. B-ASIC Scheduler-gui Logger Module.
......
...@@ -1021,6 +1021,7 @@ def start_scheduler(schedule: Optional[Schedule] = None) -> Schedule: ...@@ -1021,6 +1021,7 @@ def start_scheduler(schedule: Optional[Schedule] = None) -> Schedule:
The edited schedule. The edited schedule.
""" """
if not QApplication.instance(): if not QApplication.instance():
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(sys.argv) app = QApplication(sys.argv)
else: else:
app = QApplication.instance() app = QApplication.instance()
......
...@@ -1224,12 +1224,12 @@ class SFG(AbstractOperation): ...@@ -1224,12 +1224,12 @@ class SFG(AbstractOperation):
for outport in curr_iter_ports: for outport in curr_iter_ports:
for signal in outport.signals: for signal in outport.signals:
new_inport = signal.destination new_input_port = signal.destination
# Do not traverse over delays. # Do not traverse over delays.
if new_inport is not None and not isinstance( if new_input_port is not None and not isinstance(
new_inport.operation, Delay new_input_port.operation, Delay
): ):
new_op = new_inport.operation new_op = new_input_port.operation
remaining_inports_per_operation[new_op] -= 1 remaining_inports_per_operation[new_op] -= 1
if remaining_inports_per_operation[new_op] == 0: if remaining_inports_per_operation[new_op] == 0:
next_iter_ports.extend(new_op.outputs) next_iter_ports.extend(new_op.outputs)
...@@ -1242,7 +1242,16 @@ class SFG(AbstractOperation): ...@@ -1242,7 +1242,16 @@ class SFG(AbstractOperation):
self, original_component: GraphComponent self, original_component: GraphComponent
) -> GraphComponent: ) -> GraphComponent:
if original_component in self._original_components_to_new: if original_component in self._original_components_to_new:
raise ValueError("Tried to add duplicate SFG component") id = (
original_component.name
if original_component.name
else (
original_component.graph_id
if original_component.graph_id
else original_component.type_name()
)
)
raise ValueError(f"Tried to add duplicate SFG component: {id}")
new_component = original_component.copy() new_component = original_component.copy()
self._original_components_to_new[original_component] = new_component self._original_components_to_new[original_component] = new_component
if not new_component.graph_id or new_component.graph_id in self._used_ids: if not new_component.graph_id or new_component.graph_id in self._used_ids:
...@@ -1273,7 +1282,16 @@ class SFG(AbstractOperation): ...@@ -1273,7 +1282,16 @@ class SFG(AbstractOperation):
# Connect input ports to new signals. # Connect input ports to new signals.
for original_input_port in original_op.inputs: for original_input_port in original_op.inputs:
if original_input_port.signal_count < 1: if original_input_port.signal_count < 1:
raise ValueError("Unconnected input port in SFG") id = (
original_op.name
if original_op.name
else (
original_op.graph_id
if original_op.graph_id
else original_op.type_name()
)
)
raise ValueError(f"Unconnected input port in SFG. Operation: {id}")
for original_signal in original_input_port.signals: for original_signal in original_input_port.signals:
# Check if the signal is one of the SFG's input signals. # Check if the signal is one of the SFG's input signals.
...@@ -1509,7 +1527,7 @@ class SFG(AbstractOperation): ...@@ -1509,7 +1527,7 @@ class SFG(AbstractOperation):
def sfg_digraph( def sfg_digraph(
self, self,
show_id: bool = False, show_signal_id: bool = False,
engine: Optional[str] = None, engine: Optional[str] = None,
branch_node: bool = True, branch_node: bool = True,
port_numbering: bool = True, port_numbering: bool = True,
...@@ -1522,7 +1540,7 @@ class SFG(AbstractOperation): ...@@ -1522,7 +1540,7 @@ class SFG(AbstractOperation):
Parameters Parameters
---------- ----------
show_id : bool, default: False show_signal_id : bool, default: False
If True, the graph_id:s of signals are shown. If True, the graph_id:s of signals are shown.
engine : str, optional engine : str, optional
Graphviz layout engine to be used, see https://graphviz.org/documentation/. Graphviz layout engine to be used, see https://graphviz.org/documentation/.
...@@ -1554,7 +1572,7 @@ class SFG(AbstractOperation): ...@@ -1554,7 +1572,7 @@ class SFG(AbstractOperation):
if branch_node and source.signal_count > 1 if branch_node and source.signal_count > 1
else source.operation.graph_id else source.operation.graph_id
) )
label = op.graph_id if show_id else None label = op.graph_id if show_signal_id else None
taillabel = ( taillabel = (
str(source.index) str(source.index)
if source.operation.output_count > 1 if source.operation.output_count > 1
...@@ -1593,7 +1611,11 @@ class SFG(AbstractOperation): ...@@ -1593,7 +1611,11 @@ class SFG(AbstractOperation):
taillabel=taillabel, taillabel=taillabel,
) )
else: else:
dg.node(op.graph_id, shape=_OPERATION_SHAPE[op.type_name()]) dg.node(
op.graph_id,
shape=_OPERATION_SHAPE[op.type_name()],
label=f"{op.name}\n({op.graph_id})" if op.name else None,
)
return dg return dg
def _repr_mimebundle_(self, include=None, exclude=None): def _repr_mimebundle_(self, include=None, exclude=None):
...@@ -1618,7 +1640,7 @@ class SFG(AbstractOperation): ...@@ -1618,7 +1640,7 @@ class SFG(AbstractOperation):
def show( def show(
self, self,
fmt: Optional[str] = None, fmt: Optional[str] = None,
show_id: bool = False, show_signal_id: bool = False,
engine: Optional[str] = None, engine: Optional[str] = None,
branch_node: bool = True, branch_node: bool = True,
port_numbering: bool = True, port_numbering: bool = True,
...@@ -1634,7 +1656,7 @@ class SFG(AbstractOperation): ...@@ -1634,7 +1656,7 @@ class SFG(AbstractOperation):
https://www.graphviz.org/doc/info/output.html https://www.graphviz.org/doc/info/output.html
Most common are "pdf", "eps", "png", and "svg". Default is None which Most common are "pdf", "eps", "png", and "svg". Default is None which
leads to PDF. leads to PDF.
show_id : bool, default: False show_signal_id : bool, default: False
If True, the graph_id:s of signals are shown. If True, the graph_id:s of signals are shown.
engine : str, optional engine : str, optional
Graphviz layout engine to be used, see https://graphviz.org/documentation/. Graphviz layout engine to be used, see https://graphviz.org/documentation/.
...@@ -1649,7 +1671,7 @@ class SFG(AbstractOperation): ...@@ -1649,7 +1671,7 @@ class SFG(AbstractOperation):
""" """
dg = self.sfg_digraph( dg = self.sfg_digraph(
show_id=show_id, show_signal_id=show_signal_id,
engine=engine, engine=engine,
branch_node=branch_node, branch_node=branch_node,
port_numbering=port_numbering, port_numbering=port_numbering,
......
...@@ -7,6 +7,7 @@ In this example, a direct form first-order IIR filter is designed. ...@@ -7,6 +7,7 @@ In this example, a direct form first-order IIR filter is designed.
First, we need to import the operations that will be used in the example: First, we need to import the operations that will be used in the example:
""" """
from b_asic.core_operations import ConstantMultiplication from b_asic.core_operations import ConstantMultiplication
from b_asic.special_operations import Delay, Input, Output from b_asic.special_operations import Delay, Input, Output
...@@ -127,7 +128,7 @@ firstorderiir.print_precedence_graph() ...@@ -127,7 +128,7 @@ firstorderiir.print_precedence_graph()
# add1 -> "add1.0" # add1 -> "add1.0"
# add1 [label=add1 shape=ellipse] # add1 [label=add1 shape=ellipse]
# } # }
# #
# As seen, each operation has an id, in addition to the optional name. # As seen, each operation has an id, in addition to the optional name.
# This can be used to access the operation. For example, # This can be used to access the operation. For example,
firstorderiir.find_by_id('cmul0') firstorderiir.find_by_id('cmul0')
......
...@@ -3,15 +3,8 @@ ...@@ -3,15 +3,8 @@
Two-tap FIR filter Two-tap FIR filter
================== ==================
""" """
from b_asic import (
SFG, from b_asic import SFG, Addition, ConstantMultiplication, Delay, Input, Output, Signal
Addition,
ConstantMultiplication,
Delay,
Input,
Output,
Signal,
)
# Inputs: # Inputs:
in0 = Input(name="in_0") in0 = Input(name="in_0")
...@@ -24,9 +17,7 @@ t0 = Delay(initial_value=0, name="t0") ...@@ -24,9 +17,7 @@ t0 = Delay(initial_value=0, name="t0")
cmul0 = ConstantMultiplication( cmul0 = ConstantMultiplication(
value=0.5, name="cmul0", latency_offsets={'in0': None, 'out0': None} value=0.5, name="cmul0", latency_offsets={'in0': None, 'out0': None}
) )
add0 = Addition( add0 = Addition(name="add0", latency_offsets={'in0': None, 'in1': None, 'out0': None})
name="add0", latency_offsets={'in0': None, 'in1': None, 'out0': None}
)
cmul1 = ConstantMultiplication( cmul1 = ConstantMultiplication(
value=0.5, name="cmul1", latency_offsets={'in0': None, 'out0': None} value=0.5, name="cmul1", latency_offsets={'in0': None, 'out0': None}
) )
......
# Legacy files # Legacy files
This folder contains currently unused code that is kept for acedemic purposes, This folder contains currently unused code that is kept for academic purposes,
or to be used as a refererence for future development. or to be used as a reference for future development.
## simulation_oop ## simulation_oop
......
...@@ -64,7 +64,7 @@ number abstract_operation::quantize_input(std::size_t index, number value, std:: ...@@ -64,7 +64,7 @@ number abstract_operation::quantize_input(std::size_t index, number value, std::
} }
if (bits > 64) { if (bits > 64) {
throw py::value_error{ throw py::value_error{
fmt::format("Cannot quantize to {} (more than 64) bits as requested by the singal connected to input #{}", bits, index)}; fmt::format("Cannot quantize to {} (more than 64) bits as requested by the signal connected to input #{}", bits, index)};
} }
return number{static_cast<number::value_type>(static_cast<std::int64_t>(value.real()) & ((std::int64_t{1} << bits) - 1))}; return number{static_cast<number::value_type>(static_cast<std::int64_t>(value.real()) & ((std::int64_t{1} << bits) - 1))};
} }
......