pybrid-computing 0.12.0__tar.gz → 0.12.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/.gitignore +8 -1
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/PKG-INFO +2 -1
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/pyproject.toml +1 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/dac/__init__.py +0 -1
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucipy/computer.py +3 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/dummy_dac.py +0 -2
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/__init__.py +0 -2
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/backplane_tblock.py +6 -10
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/carrier.py +11 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/control.py +1 -107
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/controller.py +0 -26
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/protocol/serializer.py +58 -8
- pybrid_computing-0.12.3/src/pybrid/redac/router.py +184 -0
- pybrid_computing-0.12.0/src/pybrid/mock/handler/register_external_entities.py +0 -33
- pybrid_computing-0.12.0/src/pybrid/redac/router.py +0 -159
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/README.md +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/analog/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/analog/computations.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/computer.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/controller.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/elements.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/entities.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/exceptions.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/listeners.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/modules.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/programs/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/programs/base.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/programs/recl.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/programs/state.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/run.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/serializer.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/utils.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/validators.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/proto/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/proto/io.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/proto/main_pb2.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/proto/main_pb2.pyi +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/proto/versioning.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/result.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/utils/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/utils/addressing.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/utils/descriptors.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/utils/imports.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/utils/logging.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/base/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/base/__main__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/base/base.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/base/commands.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/base/loader.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/base/ressources.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/base/shell.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/cli/dac/backend.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucidac/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucidac/computer.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucidac/controller.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucidac/front_panel.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucidac/front_plane.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucidac/protocol/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucidac/protocol/serializer.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucipy/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucipy/_compat.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucipy/circuits.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucipy/elements.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucipy/helpers.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/config.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/connection.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/base.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/calibration.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/config.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/extract.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/reset.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/start_run.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/udp_streaming.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/block.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/cblock.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/iblock.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/mblock.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/shblock.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/tblock.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/ublock.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/channel.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/cluster.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/computations.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/computer.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/connection.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/data.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/detect.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/device.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/display.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/elements.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/entities.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/modules.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/monitor.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/partitioning.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/protocol/deserializer.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/protocol/types.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/protocol/validators.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/run.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/session.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/sync.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/sim/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/sim/computer.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/sim/config.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/sim/controller.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/sim/protocol/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/sim/protocol/messages.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/sim/protocol/serializer.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/util/__init__.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/util/reporter.py +0 -0
- {pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/util/updater.py +0 -0
|
@@ -125,6 +125,7 @@ __pycache__/
|
|
|
125
125
|
.Python
|
|
126
126
|
build/
|
|
127
127
|
build-temp/
|
|
128
|
+
build_tests/
|
|
128
129
|
develop-eggs/
|
|
129
130
|
dist/
|
|
130
131
|
downloads/
|
|
@@ -394,4 +395,10 @@ objects
|
|
|
394
395
|
refs
|
|
395
396
|
|
|
396
397
|
# Generated documentation
|
|
397
|
-
public/
|
|
398
|
+
public/
|
|
399
|
+
|
|
400
|
+
# Talks developed here for code anchoring
|
|
401
|
+
talks/
|
|
402
|
+
node_modules/
|
|
403
|
+
package.json
|
|
404
|
+
package-lock.json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pybrid-computing
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.3
|
|
4
4
|
Summary: Library to interact with analog computers and analog-digital hybrid computers, in particular the LUCIDAC and REDAC computers made by anabrid
|
|
5
5
|
Project-URL: Homepage, https://anabrid.com/
|
|
6
6
|
Project-URL: Documentation, https://anabrid.dev/docs/pybrid/
|
|
@@ -28,6 +28,7 @@ Requires-Dist: pybrid-computing-native<1.0.0,>=0.1.0
|
|
|
28
28
|
Requires-Dist: pydantic>=2.11.9
|
|
29
29
|
Requires-Dist: pyi>=0.1.0
|
|
30
30
|
Requires-Dist: pyserial-asyncio>=0.6
|
|
31
|
+
Requires-Dist: reportlab>=4.4.10
|
|
31
32
|
Requires-Dist: zeroconf>=0.147.2
|
|
32
33
|
Description-Content-Type: text/markdown
|
|
33
34
|
|
|
@@ -606,7 +606,6 @@ async def proxy(listen: str, port: int, backend: tuple[str, ...], session_timeou
|
|
|
606
606
|
for spec in specs:
|
|
607
607
|
click.echo(f"Connecting to backend {spec.host}:{spec.port}...")
|
|
608
608
|
proxy_server.add_backend(spec.host, spec.port, stack=spec.stack, carrier=spec.carrier)
|
|
609
|
-
proxy_server.map_backends()
|
|
610
609
|
|
|
611
610
|
proxy_server.set_session_timeout(session_timeout)
|
|
612
611
|
proxy_server.start(listen, port)
|
|
@@ -94,6 +94,9 @@ class LucipyWrapper:
|
|
|
94
94
|
self._num_devices = len(endpoints)
|
|
95
95
|
self._device_indices = list(range(self._num_devices))
|
|
96
96
|
|
|
97
|
+
def controller(self):
|
|
98
|
+
return self._controller
|
|
99
|
+
|
|
97
100
|
def create_circuit(self, device_index: int | None = None) -> Circuit:
|
|
98
101
|
"""Create a Circuit scoped to a specific carrier's MAC address.
|
|
99
102
|
|
|
@@ -89,7 +89,6 @@ class DummyDAC:
|
|
|
89
89
|
ExtractHandler,
|
|
90
90
|
UDPStreamingHandler,
|
|
91
91
|
StartRunHandler,
|
|
92
|
-
RegisterExternalEntitiesHandler,
|
|
93
92
|
CalibrationHandler,
|
|
94
93
|
)
|
|
95
94
|
|
|
@@ -103,7 +102,6 @@ class DummyDAC:
|
|
|
103
102
|
pb.MessageV1.EXTRACT_COMMAND_FIELD_NUMBER: ExtractHandler(self),
|
|
104
103
|
pb.MessageV1.UDP_DATA_STREAMING_COMMAND_FIELD_NUMBER: UDPStreamingHandler(self),
|
|
105
104
|
pb.MessageV1.START_RUN_COMMAND_FIELD_NUMBER: StartRunHandler(self),
|
|
106
|
-
pb.MessageV1.REGISTER_EXTERNAL_ENTITIES_COMMAND_FIELD_NUMBER: RegisterExternalEntitiesHandler(self),
|
|
107
105
|
calibration_field: CalibrationHandler(self),
|
|
108
106
|
}
|
|
109
107
|
|
|
@@ -10,7 +10,6 @@ from pybrid.mock.handler.config import ConfigHandler
|
|
|
10
10
|
from pybrid.mock.handler.extract import ExtractHandler
|
|
11
11
|
from pybrid.mock.handler.udp_streaming import UDPStreamingHandler
|
|
12
12
|
from pybrid.mock.handler.start_run import StartRunHandler
|
|
13
|
-
from pybrid.mock.handler.register_external_entities import RegisterExternalEntitiesHandler
|
|
14
13
|
from pybrid.mock.handler.calibration import CalibrationHandler
|
|
15
14
|
|
|
16
15
|
__all__ = [
|
|
@@ -20,6 +19,5 @@ __all__ = [
|
|
|
20
19
|
"ExtractHandler",
|
|
21
20
|
"UDPStreamingHandler",
|
|
22
21
|
"StartRunHandler",
|
|
23
|
-
"RegisterExternalEntitiesHandler",
|
|
24
22
|
"CalibrationHandler",
|
|
25
23
|
]
|
{pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/blocks/backplane_tblock.py
RENAMED
|
@@ -12,20 +12,16 @@ from pybrid.redac.entities import EntityClass, EntityType, Loc
|
|
|
12
12
|
@EntityType.register(EntityClass.T_BLOCK_BPL)
|
|
13
13
|
@dataclass
|
|
14
14
|
class BackplaneTBlock(FunctionBlock):
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@staticmethod
|
|
18
|
-
def index(dst_sector: int, sector_lane: int) -> int:
|
|
19
|
-
assert 0 <= sector_lane < 8
|
|
20
|
-
assert 0 <= dst_sector < 9
|
|
21
|
-
return dst_sector + sector_lane * 9
|
|
15
|
+
sectors: list[list[int | None]] = field(default_factory=lambda: [[None] * 8 for _ in range(9)])
|
|
22
16
|
|
|
23
17
|
def connect(self, src_sector: int, dst_sector: int, sector_lane: int):
|
|
24
18
|
assert 0 <= src_sector < 9
|
|
25
|
-
|
|
19
|
+
assert 0 <= dst_sector < 9
|
|
20
|
+
assert 0 <= sector_lane < 8
|
|
21
|
+
self.sectors[dst_sector][sector_lane] = src_sector
|
|
26
22
|
|
|
27
23
|
def source(self, dst_sector: int, sector_lane: int) -> int:
|
|
28
|
-
return self.
|
|
24
|
+
return self.sectors[dst_sector][sector_lane]
|
|
29
25
|
|
|
30
26
|
def reset(self):
|
|
31
|
-
self.
|
|
27
|
+
self.sectors = [[None] * 8 for _ in range(9)]
|
|
@@ -8,6 +8,7 @@ import logging
|
|
|
8
8
|
import warnings
|
|
9
9
|
from dataclasses import dataclass, field
|
|
10
10
|
from typing import Optional, TYPE_CHECKING
|
|
11
|
+
from enum import Enum
|
|
11
12
|
|
|
12
13
|
from pybrid.base.hybrid import EntityDoesNotExist
|
|
13
14
|
from pybrid.redac.blocks import TBlock
|
|
@@ -32,6 +33,12 @@ class ADCChannel:
|
|
|
32
33
|
#: Probe: relates this ADC channel to an input function (e.g. a problem description, such as an ODE)
|
|
33
34
|
probe: int = -1
|
|
34
35
|
|
|
36
|
+
class FrontPanelIOMode(int, Enum):
|
|
37
|
+
ANALOG_OUT = 0
|
|
38
|
+
ANALOG_IN = 1
|
|
39
|
+
DIGITAL_OUT = 2
|
|
40
|
+
DIGITAL_IN = 3
|
|
41
|
+
|
|
35
42
|
@dataclass(kw_only=True)
|
|
36
43
|
class Carrier(Entity):
|
|
37
44
|
"""
|
|
@@ -48,8 +55,12 @@ class Carrier(Entity):
|
|
|
48
55
|
adc_config: list[Optional[ADCChannel]] = field(default_factory=list)
|
|
49
56
|
|
|
50
57
|
#: ACL Select for analog I/O - note that while not supported in HW, the firmware ignores this.
|
|
58
|
+
#: This is the LUCIDAC implementation.
|
|
51
59
|
acl_select: Optional[list[str]] = None
|
|
52
60
|
|
|
61
|
+
#: Current implementation of the FrontPlane on REDACs (no specific entity)
|
|
62
|
+
front_panel_io: Optional[list[FrontPanelIOMode]] = None
|
|
63
|
+
|
|
53
64
|
#: List of clusters on the carrier board.
|
|
54
65
|
clusters: list[Cluster]
|
|
55
66
|
|
|
@@ -15,10 +15,8 @@ executor when multiple channels run concurrently.
|
|
|
15
15
|
|
|
16
16
|
import asyncio
|
|
17
17
|
import logging
|
|
18
|
-
import time
|
|
19
18
|
from concurrent.futures import ThreadPoolExecutor
|
|
20
19
|
from typing import Callable
|
|
21
|
-
from uuid import uuid4
|
|
22
20
|
|
|
23
21
|
import pybrid.base.proto.main_pb2 as pb
|
|
24
22
|
from pybrid.base.result import Result
|
|
@@ -52,16 +50,12 @@ class AsyncControlChannel:
|
|
|
52
50
|
def __init__(
|
|
53
51
|
self,
|
|
54
52
|
native: "NativeControlChannel",
|
|
55
|
-
max_busy_wait: float = 30.0,
|
|
56
53
|
):
|
|
57
54
|
"""
|
|
58
55
|
Args:
|
|
59
|
-
native:
|
|
60
|
-
max_busy_wait: Maximum time in seconds to wait when a ``busy_response``
|
|
61
|
-
is received before raising :class:`TimeoutError`.
|
|
56
|
+
native: A connected ``NativeControlChannel`` instance.
|
|
62
57
|
"""
|
|
63
58
|
self._native = native
|
|
64
|
-
self._max_busy_wait = max_busy_wait
|
|
65
59
|
self._executor = ThreadPoolExecutor(
|
|
66
60
|
max_workers=1,
|
|
67
61
|
thread_name_prefix="ctrl-channel",
|
|
@@ -159,71 +153,6 @@ class AsyncControlChannel:
|
|
|
159
153
|
"""``True`` if the C++ recv thread is active."""
|
|
160
154
|
return self._native.is_running()
|
|
161
155
|
|
|
162
|
-
async def send(self, msg: pb.MessageV1) -> None:
|
|
163
|
-
"""Fire-and-forget send — queues the serialized message for async TCP transmission."""
|
|
164
|
-
self._native.send(msg.SerializeToString())
|
|
165
|
-
|
|
166
|
-
async def _raw_send_and_recv(
|
|
167
|
-
self,
|
|
168
|
-
msg: pb.MessageV1,
|
|
169
|
-
timeout: float = 5.0,
|
|
170
|
-
) -> pb.MessageV1:
|
|
171
|
-
"""Low-level send + receive without busy-wait retry logic.
|
|
172
|
-
|
|
173
|
-
Factored out from :meth:`send_and_recv` so the busy-wait loop can
|
|
174
|
-
call it without infinite recursion.
|
|
175
|
-
"""
|
|
176
|
-
data = msg.SerializeToString()
|
|
177
|
-
loop = asyncio.get_running_loop()
|
|
178
|
-
response_bytes = await loop.run_in_executor(
|
|
179
|
-
self._executor,
|
|
180
|
-
self._native.send_and_recv,
|
|
181
|
-
data,
|
|
182
|
-
timeout,
|
|
183
|
-
)
|
|
184
|
-
response = pb.MessageV1()
|
|
185
|
-
response.ParseFromString(response_bytes)
|
|
186
|
-
return response
|
|
187
|
-
|
|
188
|
-
async def send_and_recv(
|
|
189
|
-
self,
|
|
190
|
-
msg: pb.MessageV1,
|
|
191
|
-
timeout: float = 5.0,
|
|
192
|
-
) -> pb.MessageV1:
|
|
193
|
-
"""Send a request and await the matching response.
|
|
194
|
-
|
|
195
|
-
If the proxy returns a ``busy_response``, polls with
|
|
196
|
-
:class:`pb.PingCommand` every second until the session becomes active,
|
|
197
|
-
then re-sends the original message.
|
|
198
|
-
|
|
199
|
-
:raises TimeoutError: If the device remains busy longer than
|
|
200
|
-
``max_busy_wait`` seconds.
|
|
201
|
-
"""
|
|
202
|
-
response = await self._raw_send_and_recv(msg, timeout)
|
|
203
|
-
|
|
204
|
-
if response.HasField("busy_response"):
|
|
205
|
-
logger.info("Device busy, waiting for session to become active...")
|
|
206
|
-
start_time = time.monotonic()
|
|
207
|
-
while True:
|
|
208
|
-
elapsed = time.monotonic() - start_time
|
|
209
|
-
if elapsed >= self._max_busy_wait:
|
|
210
|
-
logger.warning("Device busy timeout after %.1fs (max_busy_wait=%.1fs)", elapsed, self._max_busy_wait)
|
|
211
|
-
raise TimeoutError(
|
|
212
|
-
f"Device busy for {elapsed:.1f}s, exceeded max wait "
|
|
213
|
-
f"of {self._max_busy_wait}s"
|
|
214
|
-
)
|
|
215
|
-
await asyncio.sleep(1.0)
|
|
216
|
-
ping_msg = self._new_message(pb.PingCommand())
|
|
217
|
-
ping_response = await self._raw_send_and_recv(ping_msg, timeout)
|
|
218
|
-
if ping_response.HasField("busy_response"):
|
|
219
|
-
logger.info("Still waiting... (%.0fs elapsed)", time.monotonic() - start_time)
|
|
220
|
-
else:
|
|
221
|
-
logger.info("Session active, proceeding.")
|
|
222
|
-
break
|
|
223
|
-
response = await self._raw_send_and_recv(msg, timeout)
|
|
224
|
-
|
|
225
|
-
return response
|
|
226
|
-
|
|
227
156
|
def register_callback(self, field_number: int, callback: Callable) -> None:
|
|
228
157
|
"""Register a callback for a specific message field number.
|
|
229
158
|
|
|
@@ -255,24 +184,6 @@ class AsyncControlChannel:
|
|
|
255
184
|
def unregister_callback(self, field_number: int) -> None:
|
|
256
185
|
self._native.unregister_callback(field_number)
|
|
257
186
|
|
|
258
|
-
@staticmethod
|
|
259
|
-
def _new_message(body) -> pb.MessageV1:
|
|
260
|
-
"""Build a :class:`pb.MessageV1` wrapping *body* in the correct oneof field."""
|
|
261
|
-
msg = pb.MessageV1(id=str(uuid4()))
|
|
262
|
-
fields = msg.DESCRIPTOR.oneofs_by_name["kind"].fields
|
|
263
|
-
for field in fields:
|
|
264
|
-
if field.message_type == body.DESCRIPTOR:
|
|
265
|
-
getattr(msg, field.name).CopyFrom(body)
|
|
266
|
-
return msg
|
|
267
|
-
raise ValueError(f"No MessageV1 oneof field for {type(body).__name__}")
|
|
268
|
-
|
|
269
|
-
@staticmethod
|
|
270
|
-
def _to_result(response: pb.MessageV1) -> Result:
|
|
271
|
-
"""Convert a response message to a :class:`~pybrid.base.result.Result`."""
|
|
272
|
-
if response.HasField("error_message"):
|
|
273
|
-
return Result.failure(response.error_message.description)
|
|
274
|
-
return Result.success()
|
|
275
|
-
|
|
276
187
|
async def extract(
|
|
277
188
|
self,
|
|
278
189
|
path: "str | Path | None" = None,
|
|
@@ -360,23 +271,6 @@ class AsyncControlChannel:
|
|
|
360
271
|
except RuntimeError as e:
|
|
361
272
|
return Result.failure(str(e))
|
|
362
273
|
|
|
363
|
-
async def register_external_entities(
|
|
364
|
-
self,
|
|
365
|
-
entities: dict[str, tuple[int, int, int, int]],
|
|
366
|
-
timeout: float = 5.0,
|
|
367
|
-
) -> Result:
|
|
368
|
-
"""Send a ``RegisterExternalEntitiesCommand`` with the given entity map.
|
|
369
|
-
|
|
370
|
-
No C++ convenience method exists — builds protobuf in Python.
|
|
371
|
-
"""
|
|
372
|
-
cmd = pb.RegisterExternalEntitiesCommand()
|
|
373
|
-
for mac, ip_octets in entities.items():
|
|
374
|
-
addr = pb.Address(data=bytes(ip_octets))
|
|
375
|
-
cmd.entities[mac].CopyFrom(addr)
|
|
376
|
-
msg = self._new_message(cmd)
|
|
377
|
-
response = await self.send_and_recv(msg, timeout)
|
|
378
|
-
return self._to_result(response)
|
|
379
|
-
|
|
380
274
|
async def reset(
|
|
381
275
|
self,
|
|
382
276
|
*,
|
|
@@ -309,32 +309,6 @@ class Controller(BaseController):
|
|
|
309
309
|
result = await session.execute()
|
|
310
310
|
return result[0] if result else run
|
|
311
311
|
|
|
312
|
-
async def register_external_entities(self):
|
|
313
|
-
"""Distribute carrier MACs and IP addresses to every connected device.
|
|
314
|
-
|
|
315
|
-
Builds a map of ``{carrier_mac: ip_octets}`` from all carriers
|
|
316
|
-
in :attr:`computer` and sends a ``RegisterExternalEntitiesCommand`` to
|
|
317
|
-
each unique backend connection.
|
|
318
|
-
"""
|
|
319
|
-
|
|
320
|
-
# TODO: reinstate once implemented in the firmware
|
|
321
|
-
logger.warning("RegisterExternalEntities command skipped...")
|
|
322
|
-
return
|
|
323
|
-
|
|
324
|
-
if not self.computer.carriers:
|
|
325
|
-
return
|
|
326
|
-
|
|
327
|
-
entities: dict[str, tuple[int, int, int, int]] = {}
|
|
328
|
-
for carrier in self.computer.carriers:
|
|
329
|
-
conn = self.connection_manager.get_connection(carrier.path)
|
|
330
|
-
host = conn.control.remote_host
|
|
331
|
-
octets = tuple(int(x) for x in host.split("."))
|
|
332
|
-
entities[str(carrier.path)] = octets
|
|
333
|
-
|
|
334
|
-
for conn in self.connection_manager.get_unique_connections():
|
|
335
|
-
result = await conn.control.register_external_entities(entities)
|
|
336
|
-
result.raise_on_error()
|
|
337
|
-
|
|
338
312
|
async def reset(self, keep_calibration: bool = True, sync: bool = True):
|
|
339
313
|
"""Reset all carrier boards to initial configuration."""
|
|
340
314
|
for conn in self.connection_manager.get_unique_connections():
|
|
@@ -14,7 +14,7 @@ from pybrid.base.proto import main_pb2 as pb
|
|
|
14
14
|
from pybrid.redac.blocks import (
|
|
15
15
|
CBlock, MMulBlock, TBlock, MIntBlock, UBlock, IBlock, MMDRBlock
|
|
16
16
|
)
|
|
17
|
-
from pybrid.redac.carrier import Carrier, ADCChannel
|
|
17
|
+
from pybrid.redac.carrier import Carrier, ADCChannel, FrontPanelIOMode
|
|
18
18
|
from pybrid.redac.blocks.backplane_tblock import BackplaneTBlock
|
|
19
19
|
from pybrid.redac.cluster import Cluster
|
|
20
20
|
from pybrid.redac.device import Device
|
|
@@ -74,6 +74,22 @@ class REDACSerializer(Serializer):
|
|
|
74
74
|
acl_select.append(pb.PortConfig.AclState.EXTERNAL if \
|
|
75
75
|
interface.lower() == "external" else pb.PortConfig.AclState.INTERNAL)
|
|
76
76
|
|
|
77
|
+
# Front Panel ports for mREDAC
|
|
78
|
+
if entity.front_panel_io:
|
|
79
|
+
front_panel_io_config = self.cc.new_config(entity).front_panel_io_config
|
|
80
|
+
|
|
81
|
+
for mode in entity.front_panel_io:
|
|
82
|
+
if mode == FrontPanelIOMode.ANALOG_OUT:
|
|
83
|
+
front_panel_io_config.io_modes.append(pb.FrontPanelIOConfig.FrontPanelIOMode.ANALOG_OUT)
|
|
84
|
+
elif mode == FrontPanelIOMode.ANALOG_IN:
|
|
85
|
+
front_panel_io_config.io_modes.append(pb.FrontPanelIOConfig.FrontPanelIOMode.ANALOG_IN)
|
|
86
|
+
elif mode == FrontPanelIOMode.DIGITAL_OUT:
|
|
87
|
+
front_panel_io_config.io_modes.append(pb.FrontPanelIOConfig.FrontPanelIOMode.DIGITAL_OUT)
|
|
88
|
+
elif mode == FrontPanelIOMode.DIGITAL_IN:
|
|
89
|
+
front_panel_io_config.io_modes.append(pb.FrontPanelIOConfig.FrontPanelIOMode.DIGITAL_IN)
|
|
90
|
+
else:
|
|
91
|
+
logger.warning(f"Unknown FrontPanelIO value: {mode}")
|
|
92
|
+
|
|
77
93
|
@_serialize_configuration.register
|
|
78
94
|
def _(self, entity: CBlock):
|
|
79
95
|
coef_config = self.cc.new_config(entity).coef_config
|
|
@@ -160,10 +176,15 @@ class REDACSerializer(Serializer):
|
|
|
160
176
|
@_serialize_configuration.register
|
|
161
177
|
def _(self, entity: BackplaneTBlock):
|
|
162
178
|
switch_config = self.cc.new_config(entity).bpl_switch_config
|
|
163
|
-
for
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
179
|
+
for sector_out, lane_ins in enumerate(entity.sectors):
|
|
180
|
+
for lane_in, sector_in in enumerate(lane_ins):
|
|
181
|
+
if lane_ins is None:
|
|
182
|
+
continue
|
|
183
|
+
|
|
184
|
+
if sector_in == 8:
|
|
185
|
+
sector_in = sector_out
|
|
186
|
+
|
|
187
|
+
switch_config.muxes.append(pb.Mux(state=sector_in, index=9 * lane_in + sector_out))
|
|
167
188
|
|
|
168
189
|
if len(switch_config.muxes) == 0:
|
|
169
190
|
self.cc.pop_config()
|
|
@@ -622,15 +643,25 @@ class REDACDeserializer(Deserializer):
|
|
|
622
643
|
def _(self, config: pb.BPLSwitchConfig):
|
|
623
644
|
"""Deserialize switch configuration and apply to TBlock."""
|
|
624
645
|
entity_path = Path.parse(self._current_full_config.entity.path)
|
|
625
|
-
entity:
|
|
646
|
+
entity: BackplaneTBlock = self.computer.get_entity(entity_path)
|
|
626
647
|
|
|
627
648
|
is_numerated = all(obj.index == 0 for obj in config.muxes)
|
|
649
|
+
|
|
650
|
+
def connect(in_sector, idx):
|
|
651
|
+
lane = idx // 9
|
|
652
|
+
out_sector = idx % 9
|
|
653
|
+
|
|
654
|
+
if out_sector == in_sector:
|
|
655
|
+
in_sector = 8
|
|
656
|
+
|
|
657
|
+
entity.connect(in_sector, out_sector, lane)
|
|
658
|
+
|
|
628
659
|
if is_numerated:
|
|
629
660
|
for idx, mux in enumerate(config.muxes):
|
|
630
|
-
|
|
661
|
+
connect(mux.state, idx)
|
|
631
662
|
else:
|
|
632
663
|
for mux in config.muxes:
|
|
633
|
-
|
|
664
|
+
connect(mux.state, mux.index)
|
|
634
665
|
|
|
635
666
|
|
|
636
667
|
@_deserialize_configuration.register
|
|
@@ -647,4 +678,23 @@ class REDACDeserializer(Deserializer):
|
|
|
647
678
|
acl_select.append("internal")
|
|
648
679
|
entity.acl_select = acl_select
|
|
649
680
|
|
|
681
|
+
@_deserialize_configuration.register
|
|
682
|
+
def _(self, config: pb.FrontPanelIOConfig):
|
|
683
|
+
"""Deserialize front panel config from REDACs and apply to Carrier."""
|
|
684
|
+
entity_path = Path.parse(self._current_full_config.entity.path)
|
|
685
|
+
entity = self.computer.get_entity(entity_path)
|
|
686
|
+
|
|
687
|
+
io_modes = []
|
|
688
|
+
for mode in config.io_modes:
|
|
689
|
+
if mode == pb.FrontPanelIOConfig.ANALOG_OUT:
|
|
690
|
+
io_modes.append(FrontPanelIOMode.ANALOG_OUT)
|
|
691
|
+
elif mode == pb.FrontPanelIOConfig.ANALOG_IN:
|
|
692
|
+
io_modes.append(FrontPanelIOMode.ANALOG_IN)
|
|
693
|
+
elif mode == pb.FrontPanelIOConfig.DIGITAL_OUT:
|
|
694
|
+
io_modes.append(FrontPanelIOMode.DIGITAL_OUT)
|
|
695
|
+
elif mode == pb.FrontPanelIOConfig.DIGITAL_IN:
|
|
696
|
+
io_modes.append(FrontPanelIOMode.DIGITAL_IN)
|
|
697
|
+
else:
|
|
698
|
+
logger.warning(f"Unknown FrontPanelIOValue: {mode}")
|
|
650
699
|
|
|
700
|
+
entity.io_modes = io_modes
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
from typing import Dict, Set, List
|
|
3
|
+
|
|
4
|
+
from pybrid.redac.blocks import TBlock
|
|
5
|
+
from pybrid.redac.blocks.backplane_tblock import BackplaneTBlock
|
|
6
|
+
from pybrid.redac.carrier import Carrier
|
|
7
|
+
from pybrid.redac.entities import Path, Loc
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RoutingException(Exception):
|
|
11
|
+
def __init__(self, message: str = ""):
|
|
12
|
+
self.message = message
|
|
13
|
+
|
|
14
|
+
class Routing:
|
|
15
|
+
carrier_t_blocks: Dict[Loc, TBlock] = {}
|
|
16
|
+
bpl_t_blocks: Dict[Loc, Dict[int, BackplaneTBlock]] = {}
|
|
17
|
+
dummy = TBlock(Path(("dummy", "T")))
|
|
18
|
+
bpl_dummy = BackplaneTBlock(Path(("dummy", "T")))
|
|
19
|
+
|
|
20
|
+
def add_t_block(self, t_block: TBlock):
|
|
21
|
+
loc = t_block.loc()
|
|
22
|
+
if loc.is_carrier():
|
|
23
|
+
self.carrier_t_blocks[loc.carrier()] = t_block
|
|
24
|
+
|
|
25
|
+
def add_t_bpl_block(self, idx: int, t_block: BackplaneTBlock):
|
|
26
|
+
loc = t_block.loc()
|
|
27
|
+
self.bpl_t_blocks.setdefault(loc.stack(), {})[idx] = t_block
|
|
28
|
+
|
|
29
|
+
def add_carrier(self, carrier: Carrier):
|
|
30
|
+
if carrier.tblock:
|
|
31
|
+
self.add_t_block(carrier.tblock)
|
|
32
|
+
if carrier.st0block:
|
|
33
|
+
self.add_t_bpl_block(0, carrier.st0block)
|
|
34
|
+
if carrier.st1block:
|
|
35
|
+
self.add_t_bpl_block(1, carrier.st1block)
|
|
36
|
+
if carrier.st2block:
|
|
37
|
+
self.add_t_bpl_block(2, carrier.st2block)
|
|
38
|
+
|
|
39
|
+
def find_carrier_t_block(self, loc: Loc) -> TBlock:
|
|
40
|
+
return self.carrier_t_blocks.get(loc.carrier(), self.dummy)
|
|
41
|
+
|
|
42
|
+
def find_bpl_t_block(self, loc: Loc, idx: int) -> BackplaneTBlock:
|
|
43
|
+
return self.bpl_t_blocks.get(loc.stack(), {}).get(idx, self.bpl_dummy)
|
|
44
|
+
|
|
45
|
+
class Router(Routing):
|
|
46
|
+
|
|
47
|
+
# route two cluster
|
|
48
|
+
def _route_cluster(self, src: Loc, dst: Loc):
|
|
49
|
+
assert src.carrier() == dst.carrier()
|
|
50
|
+
|
|
51
|
+
if src.lane_id() < 8:
|
|
52
|
+
if src != dst:
|
|
53
|
+
raise RoutingException("First 8 lanes only to same indices routable")
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
output_sector_lane = src.lane_id() - 8
|
|
57
|
+
input_sector_lane = dst.lane_id() - 8
|
|
58
|
+
|
|
59
|
+
if output_sector_lane != input_sector_lane:
|
|
60
|
+
raise RoutingException("Connections inside cluster are only allowed between same lane indices!")
|
|
61
|
+
|
|
62
|
+
tblock = self.find_carrier_t_block(dst)
|
|
63
|
+
return tblock.connect(src.cluster_id() + 1, dst.cluster_id() + 1, input_sector_lane)
|
|
64
|
+
|
|
65
|
+
def _route_carrier(self, src: Loc, dst: Loc):
|
|
66
|
+
if src.lane_id() != dst.lane_id():
|
|
67
|
+
raise RoutingException("Connections between clusters are only allowed between same lane indices!")
|
|
68
|
+
|
|
69
|
+
if 0 <= src.lane_id() < 8:
|
|
70
|
+
raise RoutingException("Connections between clusters are only allowed between 8 to 31 lane indices!")
|
|
71
|
+
|
|
72
|
+
t_block = self.find_carrier_t_block(dst)
|
|
73
|
+
t_block.connect(src.cluster_id() + 1, dst.cluster_id() + 1, dst.lane_id() - 8)
|
|
74
|
+
|
|
75
|
+
def _route_stack(self, src: Loc, dst: Loc):
|
|
76
|
+
if src.lane_id() != dst.lane_id():
|
|
77
|
+
raise RoutingException("Connections between carrier are only allowed between same lane indices!")
|
|
78
|
+
|
|
79
|
+
if not (8 <= src.lane_id() < 32):
|
|
80
|
+
raise RoutingException("Connections between carrier are only allowed between 8 to 31 lane indices!")
|
|
81
|
+
|
|
82
|
+
offset_lane_id = src.lane_id() - 8
|
|
83
|
+
partition = offset_lane_id // 8
|
|
84
|
+
|
|
85
|
+
output_t_block = self.find_carrier_t_block(src)
|
|
86
|
+
input_t_block = self.find_carrier_t_block(dst)
|
|
87
|
+
|
|
88
|
+
#sector 0 is connect to backplane
|
|
89
|
+
#cluster 0-2 are sector 1-3
|
|
90
|
+
output_t_block.connect(src.cluster_id() + 1, 0, offset_lane_id)
|
|
91
|
+
input_t_block.connect(0, dst.cluster_id() + 1, offset_lane_id)
|
|
92
|
+
|
|
93
|
+
mod_dst_lane = dst.lane_id() % 8
|
|
94
|
+
if src.stack() != dst.stack():
|
|
95
|
+
src_bpl_t_block = self.find_bpl_t_block(src, partition)
|
|
96
|
+
dst_bpl_t_block = self.find_bpl_t_block(dst, partition)
|
|
97
|
+
|
|
98
|
+
exit_sector = 7 if src.stack_id() < dst.stack_id() else 8
|
|
99
|
+
entry_sector = 8 if src.stack_id() < dst.stack_id() else 7
|
|
100
|
+
|
|
101
|
+
src_bpl_t_block.connect(src.carrier_id(), exit_sector, mod_dst_lane)
|
|
102
|
+
dir = 1 if src.stack_id() < dst.stack_id() else -1
|
|
103
|
+
for btw_stack_idx in range(src.stack_id() + dir, dst.stack_id(), dir):
|
|
104
|
+
btw_bpl_t_block = self.find_bpl_t_block(Loc.new_stack(btw_stack_idx), partition)
|
|
105
|
+
btw_bpl_t_block.connect(entry_sector, exit_sector, mod_dst_lane)
|
|
106
|
+
|
|
107
|
+
dst_bpl_t_block.connect(entry_sector, dst.carrier_id(), mod_dst_lane)
|
|
108
|
+
else:
|
|
109
|
+
bpl_t_block = self.find_bpl_t_block(src, partition)
|
|
110
|
+
bpl_t_block.connect(src.carrier_id(), dst.carrier_id(), mod_dst_lane)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def route(self, src: Loc, dst: Loc):
|
|
114
|
+
assert src.carrier_id() < 7 and dst.carrier_id() < 7
|
|
115
|
+
assert src.cluster_id() < 3 and dst.cluster_id() < 3
|
|
116
|
+
assert dst.lane_id() < 32 and src.lane_id() < 32
|
|
117
|
+
if src.cluster() == dst.cluster():
|
|
118
|
+
return self._route_cluster(src, dst)
|
|
119
|
+
|
|
120
|
+
if src.carrier() == dst.carrier():
|
|
121
|
+
return self._route_carrier(src, dst)
|
|
122
|
+
|
|
123
|
+
return self._route_stack(src, dst)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class Tracer(Routing):
|
|
127
|
+
|
|
128
|
+
#loc is a lane in a cluster after a the t block searching for the coef source
|
|
129
|
+
#loc here is stack / carrier / cluster_id / lane
|
|
130
|
+
def find_coef(self, loc: Loc) -> typing.Optional[Loc]:
|
|
131
|
+
|
|
132
|
+
visited = set()
|
|
133
|
+
|
|
134
|
+
if loc.lane_id() < 8:
|
|
135
|
+
return loc
|
|
136
|
+
|
|
137
|
+
# only here we bump cluster_id because we need 0 for backplane
|
|
138
|
+
loc = loc.carrier() / (loc.cluster_id() + 1) / loc.lane_id()
|
|
139
|
+
|
|
140
|
+
while True:
|
|
141
|
+
if loc.lane_id() < 8:
|
|
142
|
+
return loc
|
|
143
|
+
|
|
144
|
+
if loc in visited:
|
|
145
|
+
return None
|
|
146
|
+
visited.add(loc)
|
|
147
|
+
|
|
148
|
+
carrier_t_block = self.find_carrier_t_block(loc.carrier())
|
|
149
|
+
|
|
150
|
+
# source is either the result of coef or from bpl t block
|
|
151
|
+
tblock_lane = loc.lane_id() - 8
|
|
152
|
+
source = carrier_t_block.source(loc.cluster_id(), tblock_lane)
|
|
153
|
+
if source is None or not (0 <= source < 4):
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
if source != 0:
|
|
157
|
+
return loc.carrier() / (source - 1) / loc.lane_id()
|
|
158
|
+
|
|
159
|
+
# here source is from backplane
|
|
160
|
+
current_stack = loc.stack()
|
|
161
|
+
prev_carrier_id = loc.carrier_id()
|
|
162
|
+
|
|
163
|
+
while True:
|
|
164
|
+
bpl_t_block = self.find_bpl_t_block(current_stack, tblock_lane // 8)
|
|
165
|
+
prev_carrier_id = bpl_t_block.source(prev_carrier_id, tblock_lane % 8)
|
|
166
|
+
|
|
167
|
+
if prev_carrier_id is None:
|
|
168
|
+
return None
|
|
169
|
+
elif prev_carrier_id == 8:
|
|
170
|
+
current_stack = Loc.new_stack(current_stack.stack_id() - 1)
|
|
171
|
+
prev_carrier_id = 7
|
|
172
|
+
elif prev_carrier_id == 7:
|
|
173
|
+
current_stack = Loc.new_stack(current_stack.stack_id() + 1)
|
|
174
|
+
prev_carrier_id = 8
|
|
175
|
+
else:
|
|
176
|
+
break
|
|
177
|
+
|
|
178
|
+
if 0 <= prev_carrier_id <= 6:
|
|
179
|
+
# 0 because backpanel here!
|
|
180
|
+
loc = current_stack / prev_carrier_id / 0 / loc.lane_id()
|
|
181
|
+
continue
|
|
182
|
+
else:
|
|
183
|
+
#external
|
|
184
|
+
raise RoutingException("Connections between stacks not implemented yet!")
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2022-2025 anabrid GmbH
|
|
2
|
-
# Contact: https://www.anabrid.com/licensing/
|
|
3
|
-
# SPDX-License-Identifier: MIT OR GPL-2.0-or-later
|
|
4
|
-
|
|
5
|
-
"""Handler for the register external entities command."""
|
|
6
|
-
|
|
7
|
-
from typing import TYPE_CHECKING
|
|
8
|
-
|
|
9
|
-
import pybrid.base.proto.main_pb2 as pb
|
|
10
|
-
from pybrid.mock.handler.base import BaseHandler
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from pybrid.mock.connection import ClientConnection
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class RegisterExternalEntitiesHandler(BaseHandler):
|
|
17
|
-
"""Handler for external entities registration commands.
|
|
18
|
-
|
|
19
|
-
Stores the received entity map for test inspection but performs no
|
|
20
|
-
real coordination (DummyDAC doesn't route cross-carrier signals).
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
last_entities: dict[str, bytes]
|
|
24
|
-
|
|
25
|
-
def __init__(self, server):
|
|
26
|
-
super().__init__(server)
|
|
27
|
-
self.last_entities = {}
|
|
28
|
-
|
|
29
|
-
async def handle(
|
|
30
|
-
self, cmd: pb.RegisterExternalEntitiesCommand, connection: "ClientConnection"
|
|
31
|
-
) -> pb.SuccessMessage:
|
|
32
|
-
self.last_entities = {k: v.data for k, v in cmd.entities.items()}
|
|
33
|
-
return pb.SuccessMessage()
|
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import typing
|
|
2
|
-
from typing import Dict, Set, List
|
|
3
|
-
|
|
4
|
-
from pybrid.redac.blocks import TBlock
|
|
5
|
-
from pybrid.redac.blocks.backplane_tblock import BackplaneTBlock
|
|
6
|
-
from pybrid.redac.carrier import Carrier
|
|
7
|
-
from pybrid.redac.entities import Path, Loc
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class RoutingException(Exception):
|
|
11
|
-
def __init__(self, message: str = ""):
|
|
12
|
-
self.message = message
|
|
13
|
-
|
|
14
|
-
class Routing:
|
|
15
|
-
carrier_t_blocks: Dict[Loc, TBlock] = {}
|
|
16
|
-
bpl_t_blocks: Dict[Loc, Dict[int, BackplaneTBlock]] = {}
|
|
17
|
-
dummy = TBlock(Path(("dummy", "T")))
|
|
18
|
-
bpl_dummy = BackplaneTBlock(Path(("dummy", "T")))
|
|
19
|
-
|
|
20
|
-
def add_t_block(self, t_block: TBlock):
|
|
21
|
-
loc = t_block.loc()
|
|
22
|
-
if loc.is_carrier():
|
|
23
|
-
self.carrier_t_blocks[loc.carrier()] = t_block
|
|
24
|
-
|
|
25
|
-
def add_t_bpl_block(self, idx: int, t_block: BackplaneTBlock):
|
|
26
|
-
loc = t_block.loc()
|
|
27
|
-
self.bpl_t_blocks.setdefault(loc.stack(), {})[idx] = t_block
|
|
28
|
-
|
|
29
|
-
def add_carrier(self, carrier: Carrier):
|
|
30
|
-
if carrier.tblock:
|
|
31
|
-
self.add_t_block(carrier.tblock)
|
|
32
|
-
if carrier.st0block:
|
|
33
|
-
self.add_t_bpl_block(0, carrier.st0block)
|
|
34
|
-
if carrier.st1block:
|
|
35
|
-
self.add_t_bpl_block(1, carrier.st1block)
|
|
36
|
-
if carrier.st2block:
|
|
37
|
-
self.add_t_bpl_block(2, carrier.st2block)
|
|
38
|
-
|
|
39
|
-
def find_carrier_t_block(self, loc: Loc) -> TBlock:
|
|
40
|
-
return self.carrier_t_blocks.get(loc.carrier(), self.dummy)
|
|
41
|
-
|
|
42
|
-
def find_bpl_t_block(self, loc: Loc, idx: int) -> BackplaneTBlock:
|
|
43
|
-
return self.bpl_t_blocks.get(loc.stack(), {}).get(idx, self.bpl_dummy)
|
|
44
|
-
|
|
45
|
-
class Router(Routing):
|
|
46
|
-
|
|
47
|
-
# route two cluster
|
|
48
|
-
def _route_cluster(self, output: Loc, input: Loc):
|
|
49
|
-
assert output.carrier() == input.carrier()
|
|
50
|
-
|
|
51
|
-
if output.lane_id() < 8:
|
|
52
|
-
if output != input:
|
|
53
|
-
raise RoutingException("First 8 lanes only to same indices routable")
|
|
54
|
-
return None
|
|
55
|
-
|
|
56
|
-
output_sector_lane = output.lane_id() - 8
|
|
57
|
-
input_sector_lane = input.lane_id() - 8
|
|
58
|
-
|
|
59
|
-
if output_sector_lane != input_sector_lane:
|
|
60
|
-
raise RoutingException("Connections inside cluster only allowed between same lane indices!")
|
|
61
|
-
|
|
62
|
-
tblock = self.find_carrier_t_block(input)
|
|
63
|
-
return tblock.connect(output.cluster_id() + 1, input.cluster_id() + 1, input_sector_lane)
|
|
64
|
-
|
|
65
|
-
def _route_carrier(self, output: Loc, input: Loc):
|
|
66
|
-
if output.lane_id() != input.lane_id():
|
|
67
|
-
raise RoutingException("Connections between clusters only allowed between same lane indices!")
|
|
68
|
-
|
|
69
|
-
if 0 <= output.lane_id() < 8:
|
|
70
|
-
raise RoutingException("Connections between clusters only allowed between 8 to 31 lane indices!")
|
|
71
|
-
|
|
72
|
-
t_block = self.find_carrier_t_block(input)
|
|
73
|
-
t_block.connect(output.cluster_id() + 1, input.cluster_id() + 1, input.lane_id() - 8)
|
|
74
|
-
|
|
75
|
-
def _route_stack(self, output: Loc, input: Loc):
|
|
76
|
-
if output.lane_id() != input.lane_id():
|
|
77
|
-
raise RoutingException("Connections between carrier only allowed between same lane indices!")
|
|
78
|
-
|
|
79
|
-
if not (8 <= output.lane_id() < 32 ):
|
|
80
|
-
raise RoutingException("Connections between carrier only allowed between 8 to 31 lane indices!")
|
|
81
|
-
|
|
82
|
-
offset_lane_id = output.lane_id() - 8
|
|
83
|
-
partition = offset_lane_id // 8
|
|
84
|
-
|
|
85
|
-
output_t_block = self.find_carrier_t_block(output)
|
|
86
|
-
input_t_block = self.find_carrier_t_block(input)
|
|
87
|
-
|
|
88
|
-
#index 0 is connect to backplane
|
|
89
|
-
#cluster 0-2 are sector 1-3
|
|
90
|
-
output_t_block.connect(output.cluster_id() + 1, 0, offset_lane_id)
|
|
91
|
-
input_t_block.connect(0, input.cluster_id() + 1, offset_lane_id)
|
|
92
|
-
|
|
93
|
-
bpl_t_block = self.find_bpl_t_block(output, partition)
|
|
94
|
-
bpl_t_block.connect(output.carrier_id(), input.carrier_id(), input.lane_id() % 8)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def route(self, output: Loc, input: Loc):
|
|
98
|
-
assert output.stack_id() < 2 and input.stack_id() < 2
|
|
99
|
-
assert output.carrier_id() < 7 and input.carrier_id() < 7
|
|
100
|
-
assert output.cluster_id() < 3 and input.cluster_id() < 3
|
|
101
|
-
assert input.lane_id() < 32 and output.lane_id() < 32
|
|
102
|
-
if output.cluster() == input.cluster():
|
|
103
|
-
return self._route_cluster(output, input)
|
|
104
|
-
|
|
105
|
-
if output.carrier() == input.carrier():
|
|
106
|
-
return self._route_carrier(output, input)
|
|
107
|
-
|
|
108
|
-
if output.stack() == input.stack():
|
|
109
|
-
return self._route_stack(output, input)
|
|
110
|
-
|
|
111
|
-
raise RoutingException("Connections between stacks not implemented yet!")
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
class Tracer(Routing):
|
|
115
|
-
|
|
116
|
-
#loc is a lane in a cluster after a the t block searching for the coef source
|
|
117
|
-
#loc here is stack / carrier / cluster_id / lane
|
|
118
|
-
def find_coef(self, loc: Loc) -> typing.Optional[Loc]:
|
|
119
|
-
|
|
120
|
-
visited = set()
|
|
121
|
-
|
|
122
|
-
if loc.lane_id() < 8:
|
|
123
|
-
return loc
|
|
124
|
-
|
|
125
|
-
# only here we bump cluster_id because we need 0 for backplane
|
|
126
|
-
loc = loc.carrier() / (loc.cluster_id() + 1) / loc.lane_id()
|
|
127
|
-
|
|
128
|
-
while True:
|
|
129
|
-
if loc.lane_id() < 8:
|
|
130
|
-
return loc
|
|
131
|
-
|
|
132
|
-
if loc in visited:
|
|
133
|
-
return None
|
|
134
|
-
visited.add(loc)
|
|
135
|
-
|
|
136
|
-
carrier_t_block = self.find_carrier_t_block(loc.carrier())
|
|
137
|
-
|
|
138
|
-
# source is either the result of coef or from bpl t block
|
|
139
|
-
tblock_lane = loc.lane_id() - 8
|
|
140
|
-
source = carrier_t_block.source(loc.cluster_id(), tblock_lane)
|
|
141
|
-
if source is None or not (0 <= source < 4):
|
|
142
|
-
return None
|
|
143
|
-
|
|
144
|
-
if source != 0:
|
|
145
|
-
return loc.carrier() / (source - 1) / loc.lane_id()
|
|
146
|
-
|
|
147
|
-
# here source is from backpanel
|
|
148
|
-
bpl_t_block = self.find_bpl_t_block(loc, tblock_lane // 8)
|
|
149
|
-
prev_carrier_id = bpl_t_block.source(loc.carrier_id(), tblock_lane % 8)
|
|
150
|
-
if prev_carrier_id is None:
|
|
151
|
-
return None
|
|
152
|
-
|
|
153
|
-
if 0 <= prev_carrier_id <= 6:
|
|
154
|
-
# 0 because backpanel here!
|
|
155
|
-
loc = loc.stack() / prev_carrier_id / 0 / loc.lane_id()
|
|
156
|
-
continue
|
|
157
|
-
else:
|
|
158
|
-
#external
|
|
159
|
-
raise RoutingException("Connections between stacks not implemented yet!")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/programs/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/base/hybrid/programs/state.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/lucidac/protocol/serializer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/mock/handler/udp_streaming.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pybrid_computing-0.12.0 → pybrid_computing-0.12.3}/src/pybrid/redac/protocol/deserializer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|