Unverified Commit 26511db0 authored by Jakob Görgen's avatar Jakob Görgen
Browse files

added logic for creating socket paths

parent bdea721b
......@@ -21,6 +21,7 @@
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from simbricks.orchestration import simulation
from simbricks.orchestration import system
import enum
import pathlib
......@@ -44,11 +45,13 @@ class InstantiationEnvironment:
repo_path: str = pathlib.Path(__file__).parents[3].resolve(),
workdir: str = pathlib.Path(),
cpdir: str = pathlib.Path(),
shm_base: str = pathlib.Path(),
):
# TODO: add more parameters that wont change during instantiation
self._repodir: str = pathlib.Path(repo_path).absolute()
self._workdir: str = pathlib.Path(workdir).absolute()
self._cpdir: str = pathlib.Path(cpdir).absolute()
self._shm_base = pathlib.Path(workdir).joinpath(shm_base).absolute()
class Instantiation:
......@@ -60,23 +63,70 @@ class Instantiation:
self._env: InstantiationEnvironment = env
self._socket_tracker: set[tuple[simulation.channel.Channel, SockType]] = set()
def get_socket_path(self, chan: simulation.channel.Channel) -> Socket:
@staticmethod
def is_absolute_exists(path: str) -> bool:
path = pathlib.Path(path)
return path.is_absolute() and path.is_file()
# def dev_pci_path(self, sim) -> str:
# return f"{self.workdir}/dev.pci.{sim.name}"
#
# def dev_mem_path(self, sim: "simulators.Simulator") -> str:
# return f"{self.workdir}/dev.mem.{sim.name}"
#
# def nic_eth_path(self, sim: "simulators.Simulator") -> str:
# return f"{self.workdir}/nic.eth.{sim.name}"
#
# def dev_shm_path(self, sim: "simulators.Simulator") -> str:
# return f"{self.shm_base}/dev.shm.{sim.name}"
#
# def n2n_eth_path(
# self, sim_l: "simulators.Simulator", sim_c: "simulators.Simulator", suffix=""
# ) -> str:
# return f"{self.workdir}/n2n.eth.{sim_l.name}.{sim_c.name}.{suffix}"
#
# def net2host_eth_path(self, sim_n, sim_h) -> str:
# return f"{self.workdir}/n2h.eth.{sim_n.name}.{sim_h.name}"
#
# def net2host_shm_path(
# self, sim_n: "simulators.Simulator", sim_h: "simulators.Simulator"
# ) -> str:
# return f"{self.workdir}/n2h.shm.{sim_n.name}.{sim_h.name}"
#
# def proxy_shm_path(self, sim: "simulators.Simulator") -> str:
# return f"{self.shm_base}/proxy.shm.{sim.name}"
def _interface_to_sock_path(self, interface: system.base.Interface) -> str:
basepath = pathlib.Path(self._env._workdir)
match interface:
case PCIeHostInterface() | PCIeDeviceInterface():
return f"{self._env._shm_base}/shm.pci/{interface.component.name}.{interface._id}"
case MemDeviceInterface() | MemHostInterface():
return f"{self._env._shm_base}/shm.mem/{interface.component.name}.{interface._id}"
case EthInterface():
return f"{self._env._shm_base}/shm.eth/{interface.component.name}.{interface._id}"
case _:
raise Exception("cannot create socket path for given interface type")
def get_socket(self, interface: system.base.Interface) -> Socket:
# TODO: use self._socket_tracker to determine socket type that is needed
sock_type = SockType.LISTEN
# TODO: generate socket path
sock_path = ""
sock_path = self._interface_to_sock_path(interface=interface)
return Socket(sock_path, sock_type)
@staticmethod
def is_absolute_exists(path: str) -> bool:
path = pathlib.Path(path)
return path.is_absolute() and path.is_file()
# TODO: add more methods constructing paths as required by methods in simulators or image handling classes
def join_repo_base(self, relative_path: str) -> str:
path = pathlib.Path(self._env._repodir)
path.joinpath(relative_path)
if not path.exists():
raise Exception(f"couldn't join {self._env._repodir} and {relative_path}")
return path.absolute()
def hd_path(self, hd_name_or_path: str) -> str:
if Instantiation.is_absolute_exists(hd_name_or_path):
return hd_name_or_path
......
......@@ -37,6 +37,26 @@ class Simulator(abc.ABC):
self.experiment = e
self._components: set[sys_base.Component] = []
@staticmethod
def filter_sockets(
sockets: list[inst_base.Socket],
filter_type: inst_base.SockType = inst_base.SockType.LISTEN,
) -> list[inst_base.Socket]:
res = filter(lambda sock: sock._type == filter_type, sockets)
return res
@staticmethod
def split_sockets_by_type(
sockets: list[inst_base.Socket],
) -> tuple[sockets : list[inst_base.Socket], sockets : list[inst_base.Socket]]:
listen = Simulator.filter_sockets(
sockets=sockets, filter_type=inst_base.SockType.LISTEN
)
connect = Simulator.filter_sockets(
sockets=sockets, filter_type=inst_base.SockType.CONNECT
)
return listen, connect
def resreq_cores(self) -> int:
"""
Number of cores this simulator requires during execution.
......@@ -64,6 +84,8 @@ class Simulator(abc.ABC):
# TODO: call this in subclasses
def _add_component(self, comp: sys_base.Channel) -> None:
if comp in self._components:
raise Exception("cannot add the same specification twice to a simulator")
self._components.add(comp)
def _chan_needs_instance(self, chan: sys_base.Channel) -> bool:
......@@ -74,13 +96,35 @@ class Simulator(abc.ABC):
return False
return True
def _get_sock_path(
def _get_my_interface(self, chan: sys_base.Channel) -> sys_base.Interface:
interface = None
for inter in chan.interfaces():
if inter.component in self._components:
assert interface is None
interface = inter
if interface is None:
raise Exception(
"unable to find channel interface for simulators specification"
)
return interface
def _get_socket_and_chan(
self, inst: inst_base.Instantiation, chan: sys_base.Channel
) -> tuple[sim_chan.Channel, inst_base.Socket] | tuple[None, None]:
# check if this channel is simulator internal, i.e. doesn't need a shared memory queue
if not self._chan_needs_instance(chan):
return None, None
# create channel simualtion object
channel = self.experiment.retrieve_or_create_channel(chan)
return channel, inst.get_socket_path(channel)
# create the socket to listen on or connect to
my_interface = self._get_my_interface(chan)
socket = inst.get_socket(my_interface)
return (channel, socket)
# pylint: disable=unused-argument
@abc.abstractmethod
......
......@@ -22,7 +22,6 @@
import abc
import sys
from
from simbricks.orchestration import experiments
from simbricks.orchestration.simulation import base
from simbricks.orchestration.system import eth
......@@ -52,7 +51,7 @@ class NetSim(base.Simulator):
# TODO
def sockets_cleanup(self, env: exp_env.ExpEnv) -> list[str]:
pass
# TODO
def sockets_wait(self, env: exp_env.ExpEnv) -> list[str]:
pass
......@@ -93,10 +92,10 @@ class SwitchNet(NetSim):
run_sync = False
sockets: list[inst_base.Socket] = []
for chan in self._switch_spec.channels():
channel, socket = self._get_sock_path(inst=inst, chan=chan)
channel, socket = self._get_socket_and_chan(inst=inst, chan=chan)
if channel is None or socket is None:
continue
continue
sync_period = min(sync_period, channel.sync_period)
run_sync = run_sync or channel._synchronized
sock_paths.append(socket)
......@@ -104,25 +103,23 @@ class SwitchNet(NetSim):
assert sync_period is not None
assert eth_latency is not None
cmd = env.repodir + "/sims/net/switch/net_switch"
cmd = inst.join_repo_base("/sims/net/switch/net_switch")
cmd += f" -S {sync_period} -E {eth_latency}"
if not run_sync:
cmd += " -u"
# TODO: pcap_file --> no env!!!
if len(env.pcap_file) > 0:
cmd += " -p " + env.pcap_file
connect = ''
listen = ''
for sock in sockets:
if sock._type == inst_base.SockType.LISTEN:
listen += " -h " + sock._path
else:
connect += " -s " + sock._path
listen, connect = base.Simulator.split_sockets_by_type(sockets)
for sock in connect:
cmd += " -s " + sock._path
cmd += connect
cmd += listen
for sock in listen:
cmd += " -h " + sock._path
return cmd
......
......@@ -21,6 +21,7 @@
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import abc
import itertools
class System:
......@@ -33,11 +34,20 @@ class System:
assert c.system == self
class Component(abc.ABC):
class IdObj(abc.ABC):
__id_iter = itertools.count()
def __init__(self):
self._id = next(self.__id_iter)
class Component(IdObj):
def __init__(self, s: System) -> None:
s.system = s
s.parameters = {}
s.add_component(self)
self.name: str = ""
@abc.abstractmethod
def interfaces(self) -> list[Interface]:
......@@ -47,7 +57,7 @@ class Component(abc.ABC):
return [i.channel for i in self.interfaces() if i.is_connected()]
class Interface(abc.ABC):
class Interface(IdObj):
def __init__(self, c: Component) -> None:
self.component = c
self.channel: Channel | None = None
......@@ -63,7 +73,7 @@ class Interface(abc.ABC):
self.channel = c
class Channel(abc.ABC):
class Channel(IdObj):
def __init__(self, a: Interface, b: Interface) -> None:
self.latency = 500
self.a: Interface = a
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment