simbricks-enso-sys-py 0.6.0__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.
- simbricks_enso_sys_py-0.6.0/PKG-INFO +16 -0
- simbricks_enso_sys_py-0.6.0/pyproject.toml +50 -0
- simbricks_enso_sys_py-0.6.0/simbricks/components/enso/system/__init__.py +33 -0
- simbricks_enso_sys_py-0.6.0/simbricks/components/enso/system/data/install-enso.sh +63 -0
- simbricks_enso_sys_py-0.6.0/simbricks/components/enso/system/enso.py +231 -0
- simbricks_enso_sys_py-0.6.0/simbricks/components/enso/system/image.py +89 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simbricks-enso-sys-py
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Ensō NIC System integration into SimBricks
|
|
5
|
+
Author: Team SimBricks
|
|
6
|
+
Author-email: team@simbricks.io
|
|
7
|
+
Requires-Python: >=3.12
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
13
|
+
Requires-Dist: simbricks-imagebuild-packer (>=0.6.0)
|
|
14
|
+
Requires-Dist: simbricks-orchestration (>=0.6.0)
|
|
15
|
+
Requires-Dist: simbricks-utils (>=0.6.0)
|
|
16
|
+
Project-URL: Homepage, https://www.simbricks.io/
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2026 SimBricks
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
# furnished to do so, subject to the following conditions:
|
|
11
|
+
#
|
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
# copies or substantial portions of the Software.
|
|
14
|
+
#
|
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
# SOFTWARE.
|
|
22
|
+
|
|
23
|
+
[tool.black]
|
|
24
|
+
line-length = 100
|
|
25
|
+
|
|
26
|
+
[build-system]
|
|
27
|
+
requires = ["poetry-core>=1.0.0"]
|
|
28
|
+
build-backend = "poetry.core.masonry.api"
|
|
29
|
+
|
|
30
|
+
[tool.poetry]
|
|
31
|
+
name = "simbricks-enso-sys-py"
|
|
32
|
+
version = "0.6.0"
|
|
33
|
+
description = "Ensō NIC System integration into SimBricks"
|
|
34
|
+
authors = [
|
|
35
|
+
"Team SimBricks <team@simbricks.io>"
|
|
36
|
+
]
|
|
37
|
+
homepage = "https://www.simbricks.io/"
|
|
38
|
+
packages = [
|
|
39
|
+
{ include = "simbricks" }
|
|
40
|
+
]
|
|
41
|
+
# Guest install script, shipped as package data.
|
|
42
|
+
include = [
|
|
43
|
+
{ path = "simbricks/components/enso/system/data/*", format = ["sdist", "wheel"] }
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[tool.poetry.dependencies]
|
|
47
|
+
python = ">=3.12"
|
|
48
|
+
simbricks-orchestration = ">=0.6.0"
|
|
49
|
+
simbricks-utils = ">=0.6.0"
|
|
50
|
+
simbricks-imagebuild-packer = ">=0.6.0"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Copyright 2026 Max Planck Institute for Software Systems,
|
|
2
|
+
# National University of Singapore, Carnegie Mellon University,
|
|
3
|
+
# and SimBricks UG (haftungsbeschränkt)
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
# a copy of this software and associated documentation files (the
|
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
# the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be
|
|
14
|
+
# included in all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
22
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
from .enso import EnsoEchoServer, EnsoGen, EnsoLinuxHost, EnsoNIC
|
|
25
|
+
from .image import enso_image
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"EnsoNIC",
|
|
29
|
+
"EnsoLinuxHost",
|
|
30
|
+
"EnsoEchoServer",
|
|
31
|
+
"EnsoGen",
|
|
32
|
+
"enso_image",
|
|
33
|
+
]
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/bin/bash -eux
|
|
2
|
+
#
|
|
3
|
+
# Installs Ensō into a guest image. Run by enso_image() (see ../image.py) as
|
|
4
|
+
# the single packer layer inside the booted base image. Do not run it on your
|
|
5
|
+
# workstation: it apt-installs packages, writes to /lib/modules and installs
|
|
6
|
+
# into /usr/local.
|
|
7
|
+
#
|
|
8
|
+
# enso_image() exports ENSO_REPO / ENSO_BRANCH / ENSO_DIR ahead of the defaults
|
|
9
|
+
# below; `make guest-install` runs it with the defaults.
|
|
10
|
+
#
|
|
11
|
+
# Because packer boots the very image the driver will be loaded into, `uname -r`
|
|
12
|
+
# here is already the right kernel, so Ensō's own setup.sh does the whole job:
|
|
13
|
+
# dependencies, hugepages, the kernel module, and the meson build of the
|
|
14
|
+
# userspace with the buffer sizes the behavioral model expects.
|
|
15
|
+
#
|
|
16
|
+
# The one thing added afterwards is putting the module where modprobe can find
|
|
17
|
+
# it; setup.sh leaves it in Ensō's build tree, which would force every
|
|
18
|
+
# simulation run to rebuild it. EnsoLinuxHost only modprobes.
|
|
19
|
+
set -eux
|
|
20
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
21
|
+
|
|
22
|
+
ENSO_REPO="${ENSO_REPO:-https://github.com/crossroadsfpga/enso}"
|
|
23
|
+
ENSO_BRANCH="${ENSO_BRANCH:-simbricks-24.04}"
|
|
24
|
+
|
|
25
|
+
# Must match EnsoLinuxHost.enso_parent_dir / .enso_name.
|
|
26
|
+
ENSO_DIR="${ENSO_DIR:-/root/enso}"
|
|
27
|
+
|
|
28
|
+
KVER=$(uname -r)
|
|
29
|
+
|
|
30
|
+
# The kernel headers come with the image's kernel, whether that is a distro one
|
|
31
|
+
# or a custom SimBricks build installed from a .deb. Do not apt-install them:
|
|
32
|
+
# there is no linux-headers package to fetch for a custom kernel.
|
|
33
|
+
if [ ! -d "/lib/modules/$KVER/build" ]; then
|
|
34
|
+
echo "no kernel build tree at /lib/modules/$KVER/build -- the image needs" >&2
|
|
35
|
+
echo "the headers matching its kernel to build the Ensō driver." >&2
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# Only what Ensō's setup.sh does not install itself. sudo, because its scripts
|
|
40
|
+
# and scripts/ensogen.sh use it and the base image may not have it.
|
|
41
|
+
apt-get -y update
|
|
42
|
+
apt-get -y install build-essential git ca-certificates sudo \
|
|
43
|
+
libnuma-dev rsync bc libelf-dev kmod pkg-config
|
|
44
|
+
|
|
45
|
+
git clone "$ENSO_REPO" "$ENSO_DIR"
|
|
46
|
+
cd "$ENSO_DIR"
|
|
47
|
+
git checkout "$ENSO_BRANCH"
|
|
48
|
+
|
|
49
|
+
# Installs dependencies, reserves hugepages, builds and loads the kernel module,
|
|
50
|
+
# then meson-builds and installs the userspace. --no-quartus skips the FPGA
|
|
51
|
+
# toolchain check; it still fetches the bitstream, which we never program.
|
|
52
|
+
./setup.sh --no-quartus
|
|
53
|
+
|
|
54
|
+
# setup.sh leaves the module in the build tree, so make it modprobe-able.
|
|
55
|
+
install -Dm644 "$ENSO_DIR/software/kernel/linux/intel_fpga_pcie_drv.ko" \
|
|
56
|
+
"/lib/modules/$KVER/extra/intel_fpga_pcie_drv.ko"
|
|
57
|
+
depmod -a "$KVER"
|
|
58
|
+
|
|
59
|
+
# ensogen.sh resolves its binaries through $ENSO_DIR/build, so leave the tree in
|
|
60
|
+
# place. Check that what the application classes invoke actually exists.
|
|
61
|
+
test -x "$ENSO_DIR/build/software/examples/echo"
|
|
62
|
+
test -x "$ENSO_DIR/build/software/examples/ensogen"
|
|
63
|
+
test -x "$ENSO_DIR/build/scripts/get_pcap_pkt_size"
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Copyright 2026 Max Planck Institute for Software Systems,
|
|
2
|
+
# National University of Singapore, Carnegie Mellon University,
|
|
3
|
+
# and SimBricks UG (haftungsbeschränkt)
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
# a copy of this software and associated documentation files (the
|
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
# the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be
|
|
14
|
+
# included in all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
22
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import typing as tp
|
|
27
|
+
|
|
28
|
+
import typing_extensions as tpe
|
|
29
|
+
|
|
30
|
+
from simbricks.orchestration.system import base as sys_base
|
|
31
|
+
from simbricks.orchestration.system import nic
|
|
32
|
+
from simbricks.orchestration.system.host import app
|
|
33
|
+
from simbricks.orchestration.system.host import base as sys_host
|
|
34
|
+
from simbricks.utils import base as utils_base
|
|
35
|
+
|
|
36
|
+
if tp.TYPE_CHECKING:
|
|
37
|
+
from simbricks.orchestration.instantiation import base as inst_base
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class EnsoNIC(nic.SimplePCIeNIC):
|
|
41
|
+
"""
|
|
42
|
+
The Ensō NIC.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, s: sys_base.System) -> None:
|
|
46
|
+
super().__init__(s)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class EnsoLinuxHost(sys_host.LinuxHost):
|
|
50
|
+
"""
|
|
51
|
+
A Linux host set up to drive an :class:`EnsoNIC`.
|
|
52
|
+
|
|
53
|
+
On top of a plain Linux host this reserves hugepages, mounts ``hugetlbfs``
|
|
54
|
+
and loads Ensō's kernel driver. The Ensō checkout itself is expected to be
|
|
55
|
+
in the disk image, put there by :func:`.image.enso_image`.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
def __init__(self, s: sys_base.System) -> None:
|
|
59
|
+
super().__init__(s)
|
|
60
|
+
# Ensō reserves several GiB of hugepages, so give the guest headroom.
|
|
61
|
+
self.memory: int = 16 * 1024
|
|
62
|
+
self.cores: int = 2
|
|
63
|
+
|
|
64
|
+
self.enso_parent_dir: str = "/root"
|
|
65
|
+
self.enso_name: str = "enso"
|
|
66
|
+
|
|
67
|
+
self.nr_hugepages: int = 4096
|
|
68
|
+
|
|
69
|
+
# Ensō's kernel driver, built into the image by install-enso.sh and
|
|
70
|
+
# installed under /lib/modules/<kver>/extra, so it is modprobe'd by
|
|
71
|
+
# name.
|
|
72
|
+
self.enso_kmod: str = "intel_fpga_pcie_drv"
|
|
73
|
+
self.enso_dev_node: str = "/dev/intel_fpga_pcie_drv"
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def enso_dir(self) -> str:
|
|
77
|
+
return f"{self.enso_parent_dir}/{self.enso_name}"
|
|
78
|
+
|
|
79
|
+
def prepare_pre_cp(self, inst: inst_base.Instantiation) -> list[str]:
|
|
80
|
+
return [
|
|
81
|
+
"mount -t proc proc /proc",
|
|
82
|
+
"mount -t sysfs sysfs /sys",
|
|
83
|
+
] + super().prepare_pre_cp(inst)
|
|
84
|
+
|
|
85
|
+
def prepare_post_cp(self, inst: inst_base.Instantiation) -> list[str]:
|
|
86
|
+
# NOTE: LinuxHost.prepare_post_cp is bypassed on purpose. It walks every
|
|
87
|
+
# PCIeHostInterface whose peer is an EthSimpleNIC/SimplePCIeNIC and
|
|
88
|
+
# emits
|
|
89
|
+
# assert com._ip is not None
|
|
90
|
+
# ip link set dev ethN up
|
|
91
|
+
# ip addr add {com._ip}/24 dev ethN
|
|
92
|
+
# An EnsoNIC is a SimplePCIeNIC but exposes no kernel netdev.
|
|
93
|
+
cmds = sys_host.BaseLinuxHost.prepare_post_cp(self, inst)
|
|
94
|
+
cmds += self._hugepage_cmds()
|
|
95
|
+
cmds += self._enso_driver_cmds()
|
|
96
|
+
return cmds
|
|
97
|
+
|
|
98
|
+
def _hugepage_cmds(self) -> list[str]:
|
|
99
|
+
"""Equivalent of the hugepage section of Ensō's scripts/sw_setup.sh."""
|
|
100
|
+
return [
|
|
101
|
+
"mkdir -p /mnt/huge",
|
|
102
|
+
'mount | grep -q " /mnt/huge " || mount -t hugetlbfs hugetlbfs /mnt/huge',
|
|
103
|
+
f"echo {self.nr_hugepages} > "
|
|
104
|
+
"/sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages",
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
def _enso_driver_cmds(self) -> list[str]:
|
|
108
|
+
"""Load Ensō's kernel driver and make sure its device node exists.
|
|
109
|
+
|
|
110
|
+
Replaces the driver loop of LinuxHost.prepare_post_cp, which we skip
|
|
111
|
+
(see prepare_post_cp).
|
|
112
|
+
"""
|
|
113
|
+
cmds: list[str] = []
|
|
114
|
+
for driver in self.drivers:
|
|
115
|
+
if driver[0] == "/":
|
|
116
|
+
cmds.append(f"insmod {driver}")
|
|
117
|
+
else:
|
|
118
|
+
cmds.append(f"modprobe {driver}")
|
|
119
|
+
|
|
120
|
+
node = self.enso_dev_node
|
|
121
|
+
cmds += [
|
|
122
|
+
"modprobe uio",
|
|
123
|
+
f"modprobe {self.enso_kmod}",
|
|
124
|
+
f"test -e {node} || mknod {node} c "
|
|
125
|
+
f'$(grep -w {self.enso_kmod} /proc/devices | cut -f1 -d" ") 0',
|
|
126
|
+
f"chmod 666 {node}",
|
|
127
|
+
]
|
|
128
|
+
return cmds
|
|
129
|
+
|
|
130
|
+
def toJSON(self) -> dict:
|
|
131
|
+
json_obj = super().toJSON()
|
|
132
|
+
json_obj["enso_parent_dir"] = self.enso_parent_dir
|
|
133
|
+
json_obj["enso_name"] = self.enso_name
|
|
134
|
+
json_obj["nr_hugepages"] = self.nr_hugepages
|
|
135
|
+
json_obj["enso_kmod"] = self.enso_kmod
|
|
136
|
+
json_obj["enso_dev_node"] = self.enso_dev_node
|
|
137
|
+
return json_obj
|
|
138
|
+
|
|
139
|
+
@classmethod
|
|
140
|
+
def fromJSON(cls, system: sys_base.System, json_obj: dict) -> tpe.Self:
|
|
141
|
+
instance = super().fromJSON(system, json_obj)
|
|
142
|
+
instance.enso_parent_dir = utils_base.get_json_attr_top(json_obj, "enso_parent_dir")
|
|
143
|
+
instance.enso_name = utils_base.get_json_attr_top(json_obj, "enso_name")
|
|
144
|
+
instance.nr_hugepages = int(utils_base.get_json_attr_top(json_obj, "nr_hugepages"))
|
|
145
|
+
instance.enso_kmod = utils_base.get_json_attr_top(json_obj, "enso_kmod")
|
|
146
|
+
instance.enso_dev_node = utils_base.get_json_attr_top(json_obj, "enso_dev_node")
|
|
147
|
+
return instance
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class EnsoEchoServer(app.BaseLinuxApplication):
|
|
151
|
+
"""
|
|
152
|
+
Ensō's bundled echo example, ``build/software/examples/echo``.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
def __init__(self, h: EnsoLinuxHost) -> None:
|
|
156
|
+
utils_base.has_expected_type(h, EnsoLinuxHost)
|
|
157
|
+
super().__init__(h)
|
|
158
|
+
self.threads: int = 1
|
|
159
|
+
self.queues: int = 2
|
|
160
|
+
self.cycles: int = 0
|
|
161
|
+
|
|
162
|
+
def run_cmds(self, inst: inst_base.Instantiation) -> list[str]:
|
|
163
|
+
host = self.host
|
|
164
|
+
assert isinstance(host, EnsoLinuxHost)
|
|
165
|
+
return [
|
|
166
|
+
f"cd {host.enso_dir}",
|
|
167
|
+
f"./build/software/examples/echo {self.threads} {self.queues} {self.cycles}",
|
|
168
|
+
]
|
|
169
|
+
|
|
170
|
+
def toJSON(self) -> dict:
|
|
171
|
+
json_obj = super().toJSON()
|
|
172
|
+
json_obj["threads"] = self.threads
|
|
173
|
+
json_obj["queues"] = self.queues
|
|
174
|
+
json_obj["cycles"] = self.cycles
|
|
175
|
+
return json_obj
|
|
176
|
+
|
|
177
|
+
@classmethod
|
|
178
|
+
def fromJSON(cls, system: sys_base.System, json_obj: dict) -> tpe.Self:
|
|
179
|
+
instance = super().fromJSON(system, json_obj)
|
|
180
|
+
instance.threads = int(utils_base.get_json_attr_top(json_obj, "threads"))
|
|
181
|
+
instance.queues = int(utils_base.get_json_attr_top(json_obj, "queues"))
|
|
182
|
+
instance.cycles = int(utils_base.get_json_attr_top(json_obj, "cycles"))
|
|
183
|
+
return instance
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class EnsoGen(app.BaseLinuxApplication):
|
|
187
|
+
"""
|
|
188
|
+
Ensō's traffic generator, ``scripts/ensogen.sh``.
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
def __init__(self, h: EnsoLinuxHost) -> None:
|
|
192
|
+
utils_base.has_expected_type(h, EnsoLinuxHost)
|
|
193
|
+
super().__init__(h)
|
|
194
|
+
# None selects Ensō's bundled sample capture, relative to enso_dir.
|
|
195
|
+
self.pcap: str | None = None
|
|
196
|
+
self.count: int = 10
|
|
197
|
+
self.rate: int = 100 # Gbps
|
|
198
|
+
self.pcie_addr: str | None = None
|
|
199
|
+
|
|
200
|
+
def run_cmds(self, inst: inst_base.Instantiation) -> list[str]:
|
|
201
|
+
host = self.host
|
|
202
|
+
assert isinstance(host, EnsoLinuxHost)
|
|
203
|
+
pcap = self.pcap
|
|
204
|
+
if pcap is None:
|
|
205
|
+
pcap = f"{host.enso_dir}/scripts/sample_pcaps/2_64_1_2.pcap"
|
|
206
|
+
cmd = f"./scripts/ensogen.sh {pcap} {self.rate} --count {self.count}"
|
|
207
|
+
if self.pcie_addr is not None:
|
|
208
|
+
cmd += f" --pcie-addr {self.pcie_addr}"
|
|
209
|
+
return [
|
|
210
|
+
f"cd {host.enso_dir}",
|
|
211
|
+
f"sleep 5",
|
|
212
|
+
cmd,
|
|
213
|
+
f"sleep 5",
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
def toJSON(self) -> dict:
|
|
217
|
+
json_obj = super().toJSON()
|
|
218
|
+
json_obj["pcap"] = self.pcap
|
|
219
|
+
json_obj["count"] = self.count
|
|
220
|
+
json_obj["rate"] = self.rate
|
|
221
|
+
json_obj["pcie_addr"] = self.pcie_addr
|
|
222
|
+
return json_obj
|
|
223
|
+
|
|
224
|
+
@classmethod
|
|
225
|
+
def fromJSON(cls, system: sys_base.System, json_obj: dict) -> tpe.Self:
|
|
226
|
+
instance = super().fromJSON(system, json_obj)
|
|
227
|
+
instance.pcap = utils_base.get_json_attr_top_or_none(json_obj, "pcap")
|
|
228
|
+
instance.count = int(utils_base.get_json_attr_top(json_obj, "count"))
|
|
229
|
+
instance.rate = int(utils_base.get_json_attr_top(json_obj, "rate"))
|
|
230
|
+
instance.pcie_addr = utils_base.get_json_attr_top_or_none(json_obj, "pcie_addr")
|
|
231
|
+
return instance
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Copyright 2026 Max Planck Institute for Software Systems,
|
|
2
|
+
# National University of Singapore, Carnegie Mellon University,
|
|
3
|
+
# and SimBricks UG (haftungsbeschränkt)
|
|
4
|
+
#
|
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
# a copy of this software and associated documentation files (the
|
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
# the following conditions:
|
|
12
|
+
#
|
|
13
|
+
# The above copyright notice and this permission notice shall be
|
|
14
|
+
# included in all copies or substantial portions of the Software.
|
|
15
|
+
#
|
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
19
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
21
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
22
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
|
|
24
|
+
"""The Ensō guest image: the SimBricks base image with Ensō installed into it.
|
|
25
|
+
|
|
26
|
+
from simbricks.components.enso.system import enso_image
|
|
27
|
+
|
|
28
|
+
host.add_disk(enso_image(system))
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import pathlib
|
|
34
|
+
import shlex
|
|
35
|
+
import typing as tp
|
|
36
|
+
|
|
37
|
+
from simbricks.imagebuild.packer.image import PackerImage
|
|
38
|
+
from simbricks.orchestration.system import disk_images
|
|
39
|
+
|
|
40
|
+
if tp.TYPE_CHECKING:
|
|
41
|
+
from simbricks.orchestration.system import base as sys_base
|
|
42
|
+
|
|
43
|
+
_DATA = pathlib.Path(__file__).parent / "data"
|
|
44
|
+
|
|
45
|
+
ENSO_REPO = "https://github.com/crossroadsfpga/enso"
|
|
46
|
+
ENSO_BRANCH = "simbricks-24.04"
|
|
47
|
+
ENSO_DIR = "/root/enso"
|
|
48
|
+
DISK_SIZE = "16G"
|
|
49
|
+
BUILD_MEM_SIZE = "16G"
|
|
50
|
+
BUILD_CPUS = 4
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _script(name: str, env: dict[str, str]) -> str:
|
|
54
|
+
"""The packaged script @name with @env exported after its shebang."""
|
|
55
|
+
lines = (_DATA / name).read_text().splitlines(keepends=True)
|
|
56
|
+
exports = "".join(f"export {k}={shlex.quote(v)}\n" for k, v in sorted(env.items()))
|
|
57
|
+
return lines[0] + exports + "".join(lines[1:])
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def enso_image(
|
|
61
|
+
system: sys_base.System,
|
|
62
|
+
enso_repo: str = ENSO_REPO,
|
|
63
|
+
enso_branch: str = ENSO_BRANCH,
|
|
64
|
+
enso_dir: str = ENSO_DIR,
|
|
65
|
+
) -> PackerImage:
|
|
66
|
+
"""The SimBricks ``base`` image with Ensō installed into it.
|
|
67
|
+
|
|
68
|
+
Built with packer on the runner while the simulation is prepared; cached
|
|
69
|
+
across runs with ``simbricks-run --image-cache-dir``.
|
|
70
|
+
|
|
71
|
+
@enso_repo, @enso_branch and @enso_dir are exported into the install script
|
|
72
|
+
and are part of the image's content hash. @enso_dir has to match the
|
|
73
|
+
EnsoLinuxHost this image is attached to.
|
|
74
|
+
|
|
75
|
+
The result is an ordinary PackerImage; ``cleanup``, ``accelerator`` etc.
|
|
76
|
+
can be set on it.
|
|
77
|
+
"""
|
|
78
|
+
image = PackerImage(system, disk_images.DistroDiskImage(system, "base"))
|
|
79
|
+
image.disk_size = DISK_SIZE
|
|
80
|
+
image.mem_size = BUILD_MEM_SIZE
|
|
81
|
+
image.cpus = BUILD_CPUS
|
|
82
|
+
image.run_script_str(
|
|
83
|
+
"install-enso.sh",
|
|
84
|
+
_script(
|
|
85
|
+
"install-enso.sh",
|
|
86
|
+
{"ENSO_REPO": enso_repo, "ENSO_BRANCH": enso_branch, "ENSO_DIR": enso_dir},
|
|
87
|
+
),
|
|
88
|
+
)
|
|
89
|
+
return image
|