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