Unverified Commit 5facec96 authored by Jakob Görgen's avatar Jakob Görgen
Browse files

added simulator dependencies method to instantiation

parent ef040487
...@@ -22,7 +22,7 @@ sys = system.System() ...@@ -22,7 +22,7 @@ sys = system.System()
# create a host instance and a NIC instance then install the NIC on the host # create a host instance and a NIC instance then install the NIC on the host
host0 = system.I40ELinuxHost(sys) host0 = system.I40ELinuxHost(sys)
pcie0 = system.PCIeHostInterface(host0) pcie0 = system.PCIeHostInterface(host0)
cfg_disk0 = system.LinuxConfigDiskImage(host0) cfg_disk0 = system.DistroDiskImage(h=host0, name="base")
host0.add_disk(cfg_disk0) host0.add_disk(cfg_disk0)
host0.add_if(pcie0) host0.add_if(pcie0)
...@@ -33,7 +33,7 @@ pcichannel0 = system.PCIeChannel(pcie0, nic0._pci_if) ...@@ -33,7 +33,7 @@ pcichannel0 = system.PCIeChannel(pcie0, nic0._pci_if)
# create a host instance and a NIC instance then install the NIC on the host # create a host instance and a NIC instance then install the NIC on the host
host1 = system.I40ELinuxHost(sys) host1 = system.I40ELinuxHost(sys)
pcie1 = system.PCIeHostInterface(host1) pcie1 = system.PCIeHostInterface(host1)
cfg_disk1 = system.LinuxConfigDiskImage(host1) cfg_disk1 = system.DistroDiskImage(h=host1, name="base")
host1.add_disk(cfg_disk1) host1.add_disk(cfg_disk1)
host1.add_if(pcie0) host1.add_if(pcie0)
......
...@@ -123,7 +123,12 @@ class Instantiation(util_base.IdObj): ...@@ -123,7 +123,12 @@ class Instantiation(util_base.IdObj):
self._env: InstantiationEnvironment = env self._env: InstantiationEnvironment = env
self._executor: command_executor.Executor | None = None self._executor: command_executor.Executor | None = None
self._socket_per_interface: dict[sys_base.Interface, Socket] = {} self._socket_per_interface: dict[sys_base.Interface, Socket] = {}
self._simulation_topo: dict[] self._simulation_topo: (
dict[sys_base.Interface, set[sys_base.Interface]] | None
) = None
self._sim_dependency: (
dict[sim_base.Simulator, set[sim_base.Simulator]] | None
) = None
@staticmethod @staticmethod
def is_absolute_exists(path: str) -> bool: def is_absolute_exists(path: str) -> bool:
...@@ -162,6 +167,16 @@ class Instantiation(util_base.IdObj): ...@@ -162,6 +167,16 @@ class Instantiation(util_base.IdObj):
channel = self._get_chan_by_interface(interface=interface) channel = self._get_chan_by_interface(interface=interface)
return channel.a if channel.a is not interface else channel.b return channel.a if channel.a is not interface else channel.b
def _opposing_interface_within_same_sim(
self, interface: sys_base.Interface
) -> bool:
opposing_interface = self._get_opposing_interface(interface=interface)
component = interface.component
opposing_component = opposing_interface.component
return self.find_sim_by_spec(spec=component) == self.find_sim_by_spec(
spec=opposing_component
)
def _updated_tracker_mapping( def _updated_tracker_mapping(
self, interface: sys_base.Interface, socket: Socket self, interface: sys_base.Interface, socket: Socket
) -> None: ) -> None:
...@@ -253,19 +268,68 @@ class Instantiation(util_base.IdObj): ...@@ -253,19 +268,68 @@ class Instantiation(util_base.IdObj):
new_socket = Socket(path=sock_path, ty=sock_type) new_socket = Socket(path=sock_path, ty=sock_type)
self._updated_tracker_mapping(interface=interface, socket=new_socket) self._updated_tracker_mapping(interface=interface, socket=new_socket)
return new_socket return new_socket
def _build_simulation_topology(self) -> None: def _build_simulation_topology(self) -> None:
# TODO: FIXME
def sim_graph(self) -> dict[sim_base.Simulator, set[sim_base.Simulator]]: sim_dependency: dict[sim_base.Simulator, set[sim_base.Simulator]] = {}
sims = self._simulation.all_simulators()
graph = {} def insert_dependency(
for sim in sims: sim_a: sim_base.Simulator, depends_on: sim_base.Simulator
deps = sim.dependencies() + sim.extra_deps ):
print(f'deps of {sim}: {sim.dependencies()}') if depends_on in sim_dependency:
graph[sim] = set() assert sim_a not in sim_dependency[depends_on]
for d in deps:
graph[sim].add(d) a_dependencies = set()
return graph if sim_a in sim_dependency:
a_dependencies = sim_dependency[sim_a]
a_dependencies.add(depends_on)
sim_dependency[sim_a] = a_dependencies
def update_a_depends_on_b(sim_a: sim_base.Simulator, sim_b: sim_base.Simulator):
a_sock: set[SockType] = sim_a.supported_socket_types()
b_sock: set[SockType] = sim_b.supported_socket_types()
if a_sock != b_sock:
if len(a_sock) == 0 or len(b_sock) == 0:
raise Exception(
"cannot solve if one simulator doesnt support any socket type"
)
if SockType.CONNECT in a_sock:
assert SockType.LISTEN in b_sock
insert_dependency(sim_a, depends_on=sim_b)
else:
assert SockType.CONNECT in b_sock
insert_dependency(sim_b, depends_on=sim_a)
else:
# deadlock?
if len(a_sock) != 2 or len(b_sock) != 2:
raise Exception("cannot solve deadlock")
# both support both we just pick an order
insert_dependency(sim_a, depends_on=sim_b)
for sim in self._simulation.all_simulators():
for comp in sim._components:
for sim_inf in comp.interfaces():
# no dependency here? a.k.a both interfaces within the same simulator?
if self._opposing_interface_within_same_sim(interface=sim_inf):
continue
opposing_inf = self._get_opposing_interface(interface=sim_inf)
opposing_sim = self.find_sim_by_spec(spec=opposing_inf.component)
assert sim != opposing_sim
update_a_depends_on_b(sim, opposing_sim)
self._sim_dependency = sim_dependency
def sim_dependencies(self) -> dict[sim_base.Simulator, set[sim_base.Simulator]]:
if self._sim_dependency is not None:
return self._sim_dependency
self._build_simulation_topology()
assert self._sim_dependency is not None
return self._sim_dependency
async def cleanup_sockets( async def cleanup_sockets(
self, self,
...@@ -400,6 +464,6 @@ class Instantiation(util_base.IdObj): ...@@ -400,6 +464,6 @@ class Instantiation(util_base.IdObj):
relative_path=f"out-{run_number}.json", relative_path=f"out-{run_number}.json",
) )
def find_sim_by_spec(self, spec: sys_host.FullSystemHost) -> sim_base.Simulator: def find_sim_by_spec(self, spec: sys_base.Component) -> sim_base.Simulator:
util_base.has_expected_type(spec, sys_host.FullSystemHost) util_base.has_expected_type(spec, sys_base.Component)
return self._simulation.find_sim(spec) return self._simulation.find_sim(spec)
...@@ -53,16 +53,16 @@ class ExperimentBaseRunner(abc.ABC): ...@@ -53,16 +53,16 @@ class ExperimentBaseRunner(abc.ABC):
def sim_executor(self, simulator: sim_base.Simulator) -> command_executor.Executor: def sim_executor(self, simulator: sim_base.Simulator) -> command_executor.Executor:
pass pass
def sim_graph(self) -> dict[sim_base.Simulator, set[sim_base.Simulator]]: # def sim_graph(self) -> dict[sim_base.Simulator, set[sim_base.Simulator]]:
sims = self._simulation.all_simulators() # sims = self._simulation.all_simulators()
graph = {} # graph = {}
for sim in sims: # for sim in sims:
deps = sim.dependencies() + sim.extra_deps # deps = sim.dependencies() + sim.extra_deps
print(f'deps of {sim}: {sim.dependencies()}') # print(f'deps of {sim}: {sim.dependencies()}')
graph[sim] = set() # graph[sim] = set()
for d in deps: # for d in deps:
graph[sim].add(d) # graph[sim].add(d)
return graph # return graph
async def start_sim(self, sim: sim_base.Simulator) -> None: async def start_sim(self, sim: sim_base.Simulator) -> None:
"""Start a simulator and wait for it to be ready.""" """Start a simulator and wait for it to be ready."""
...@@ -198,7 +198,7 @@ class ExperimentBaseRunner(abc.ABC): ...@@ -198,7 +198,7 @@ class ExperimentBaseRunner(abc.ABC):
try: try:
self._out.set_start() self._out.set_start()
graph = self.sim_graph() graph = self._instantiation.sim_dependencies()
print(graph) print(graph)
ts = graphlib.TopologicalSorter(graph) ts = graphlib.TopologicalSorter(graph)
ts.prepare() ts.prepare()
......
...@@ -57,7 +57,7 @@ class Simulator(utils_base.IdObj): ...@@ -57,7 +57,7 @@ class Simulator(utils_base.IdObj):
self._relative_executable_path: str = relative_executable_path self._relative_executable_path: str = relative_executable_path
self._simulation: sim_base.Simulation = simulation self._simulation: sim_base.Simulation = simulation
self._components: set[sys_conf.Component] = set() self._components: set[sys_conf.Component] = set()
self._wait: bool = False # TODO: FIXME self._wait: bool = False # TODO: FIXME
simulation.add_sim(self) simulation.add_sim(self)
@staticmethod @staticmethod
...@@ -101,6 +101,9 @@ class Simulator(utils_base.IdObj): ...@@ -101,6 +101,9 @@ class Simulator(utils_base.IdObj):
def filter_components_by_type(self, ty) -> list[sys_conf.Component]: def filter_components_by_type(self, ty) -> list[sys_conf.Component]:
return list(filter(lambda comp: isinstance(comp, ty), self._components)) return list(filter(lambda comp: isinstance(comp, ty), self._components))
def components(self) -> set[sys_conf.Component]:
return self._components
def resreq_cores(self) -> int: def resreq_cores(self) -> int:
""" """
Number of cores this simulator requires during execution. Number of cores this simulator requires during execution.
...@@ -204,16 +207,13 @@ class Simulator(utils_base.IdObj): ...@@ -204,16 +207,13 @@ class Simulator(utils_base.IdObj):
def run_cmd(self, inst: inst_base.Instantiation) -> str: def run_cmd(self, inst: inst_base.Instantiation) -> str:
"""Command to execute this simulator.""" """Command to execute this simulator."""
return "" return ""
def checkpoint_commands(self) -> list[str]: def checkpoint_commands(self) -> list[str]:
return [] return []
# TODO: overwrite in sub-classes to reflect that currently not all adapters support both listening and connecting @abc.abstractmethod
# In future version adapters should support both which would render this method obsolete
# TODO: FIXME, this is still a little bit broken, as it might be important to create
# sockets in the correct order to not try creating a connect socket for a simulator that doesnt support it
def supported_socket_types(self) -> set[inst_base.SockType]: def supported_socket_types(self) -> set[inst_base.SockType]:
return {inst_base.SockType.LISTEN, inst_base.SockType.CONNECT} return []
# Sockets to be cleaned up: always the CONNECTING sockets # Sockets to be cleaned up: always the CONNECTING sockets
# pylint: disable=unused-argument # pylint: disable=unused-argument
......
...@@ -50,6 +50,9 @@ class HostSim(sim_base.Simulator): ...@@ -50,6 +50,9 @@ class HostSim(sim_base.Simulator):
def supported_image_formats(self) -> list[str]: def supported_image_formats(self) -> list[str]:
raise Exception("implement me") raise Exception("implement me")
def supported_socket_types(self) -> set[inst_base.SockType]:
return [inst_base.SockType.CONNECT]
class Gem5Sim(HostSim): class Gem5Sim(HostSim):
......
...@@ -40,18 +40,11 @@ class NetSim(sim_base.Simulator): ...@@ -40,18 +40,11 @@ class NetSim(sim_base.Simulator):
def full_name(self) -> str: def full_name(self) -> str:
return "net." + self.name return "net." + self.name
def dependencies(self) -> list[sim_base.Simulator]:
# TODO
deps = []
for s in self._components:
for n in s.eth_ifs:
peer_comp = n.find_peer().component
peer_sim = self._simulation.find_sim(peer_comp)
deps.append(peer_sim)
return deps
def init_network(self) -> None: def init_network(self) -> None:
pass pass
def supported_socket_types(self) -> set[inst_base.SockType]:
return [inst_base.SockType.CONNECT]
class WireNet(NetSim): class WireNet(NetSim):
......
...@@ -49,8 +49,10 @@ class PCIDevSim(base.Simulator): ...@@ -49,8 +49,10 @@ class PCIDevSim(base.Simulator):
return [inst_base.Socket(f'{inst._env._workdir}/dev.pci.{self.name}'), inst_base.Socket(f' {inst._env._shm_base}/dev.shm.{self.name}')] return [inst_base.Socket(f'{inst._env._workdir}/dev.pci.{self.name}'), inst_base.Socket(f' {inst._env._shm_base}/dev.shm.{self.name}')]
def sockets_wait(self, inst: inst_base.Instantiation) -> tp.List[str]: def sockets_wait(self, inst: inst_base.Instantiation) -> tp.List[str]:
return [inst_base.Socket(f'{inst._env._workdir}/dev.pci.{self.name}')] return [inst_base.Socket(f'{inst._env._workdir}/dev.pci.{self.name}')]
def supported_socket_types(self) -> set[inst_base.SockType]:
return [inst_base.SockType.LISTEN]
......
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