Unverified Commit 2d0931d9 authored by Jakob Görgen's avatar Jakob Görgen
Browse files

more run_cmd fixes

parent 0d2f3aab
...@@ -467,6 +467,12 @@ class Instantiation(util_base.IdObj): ...@@ -467,6 +467,12 @@ class Instantiation(util_base.IdObj):
dir_path = f"output.{sim.full_name()}-{sim._id}" dir_path = f"output.{sim.full_name()}-{sim._id}"
return self._join_paths(base=self._env._output_base, relative_path=dir_path) return self._join_paths(base=self._env._output_base, relative_path=dir_path)
def get_simulator_shm_pool_path(self, sim: sim_base.Simulator) -> str:
return self._join_paths(
base=self.shm_base_dir(),
relative_path=f"{sim.full_name()}-shm-pool-{sim._id}",
)
def get_simulation_output_path(self, run_number: int) -> str: def get_simulation_output_path(self, run_number: int) -> str:
return self._join_paths( return self._join_paths(
base=self._env._output_base, base=self._env._output_base,
......
...@@ -49,17 +49,32 @@ class Simulator(utils_base.IdObj): ...@@ -49,17 +49,32 @@ class Simulator(utils_base.IdObj):
def __init__( def __init__(
self, self,
simulation: sim_base.Simulation, simulation: sim_base.Simulation,
executable: str,
name: str = "", name: str = "",
relative_executable_path: str = "",
) -> None: ) -> None:
super().__init__() super().__init__()
self.name: str = name self.name: str = name
self._relative_executable_path: str = relative_executable_path self._executable = executable
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
self._start_tick = 0
"""The timestamp at which to start the simulation. This is useful when
the simulator is only attached at a later point in time and needs to
synchronize with connected simulators. For example, this could be used
when taking checkpoints to only attach certain simulators after the
checkpoint has been taken."""
self._extra_args: str | None = None
simulation.add_sim(self) simulation.add_sim(self)
@property
def extra_args(self) -> str:
return self._extra_args
@extra_args.setter
def extra_args(self, extra_args: str):
self._extra_args = extra_args
@staticmethod @staticmethod
def filter_sockets( def filter_sockets(
sockets: list[inst_base.Socket], sockets: list[inst_base.Socket],
...@@ -98,13 +113,19 @@ class Simulator(utils_base.IdObj): ...@@ -98,13 +113,19 @@ class Simulator(utils_base.IdObj):
raise Exception("could not determine eth_latency and sync_period") raise Exception("could not determine eth_latency and sync_period")
return latency, sync_period, run_sync return latency, sync_period, run_sync
T = tp.TypeVar("T")
def filter_components_by_pred( def filter_components_by_pred(
self, pred: tp.Callable[[sys_conf.Component], bool] self,
) -> list[sys_conf.Component]: pred: tp.Callable[[sys_conf.Component], bool],
ty: type[T] = sys_conf.Component,
) -> list[T]:
return list(filter(pred, self._components)) return list(filter(pred, self._components))
def filter_components_by_type(self, ty) -> list[sys_conf.Component]: def filter_components_by_type(self, ty: type[T]) -> list[T]:
return self.filter_components_by_pred(lambda comp: isinstance(comp, ty)) return self.filter_components_by_pred(
pred=lambda comp: isinstance(comp, ty), ty=ty
)
def components(self) -> set[sys_conf.Component]: def components(self) -> set[sys_conf.Component]:
return self._components return self._components
......
...@@ -38,8 +38,8 @@ if tp.TYPE_CHECKING: ...@@ -38,8 +38,8 @@ if tp.TYPE_CHECKING:
class HostSim(sim_base.Simulator): class HostSim(sim_base.Simulator):
def __init__(self, simulation: sim_base.Simulation, name=""): def __init__(self, simulation: sim_base.Simulation, executable: str, name=""):
super().__init__(simulation=simulation, name=name) super().__init__(simulation=simulation, executable=executable, name=name)
def full_name(self) -> str: def full_name(self) -> str:
return "host." + self.name return "host." + self.name
...@@ -60,13 +60,12 @@ class HostSim(sim_base.Simulator): ...@@ -60,13 +60,12 @@ class HostSim(sim_base.Simulator):
class Gem5Sim(HostSim): class Gem5Sim(HostSim):
def __init__(self, simulation: sim_base.Simulation): def __init__(self, simulation: sim_base.Simulation):
super().__init__(simulation=simulation, name=f"Gem5Sim-{self._id}") super().__init__(simulation=simulation, executable="sims/external/gem5/build/X86/gem5", name=f"Gem5Sim-{self._id}")
self.cpu_type_cp = "X86KvmCPU" self.cpu_type_cp = "X86KvmCPU"
self.cpu_type = "TimingSimpleCPU" self.cpu_type = "TimingSimpleCPU"
self.extra_main_args: list[str] = [] self.extra_main_args: list[str] = []
self.extra_config_args: list[str] = [] self.extra_config_args: list[str] = []
self.variant = "fast" self.variant = "fast"
self.wait = True
def resreq_cores(self) -> int: def resreq_cores(self) -> int:
return 1 return 1
...@@ -86,16 +85,19 @@ class Gem5Sim(HostSim): ...@@ -86,16 +85,19 @@ class Gem5Sim(HostSim):
) )
await task await task
def checkpoint_commands(self) -> list[str]:
return ["m5 checkpoint"]
def run_cmd(self, inst: inst_base.Instantiation) -> str: def run_cmd(self, inst: inst_base.Instantiation) -> str:
cpu_type = self.cpu_type cpu_type = self.cpu_type
if inst.create_cp(): if inst.create_cp():
cpu_type = self.cpu_type_cp cpu_type = self.cpu_type_cp
full_sys_hosts = tp.cast(list[sys_host.FullSystemHost], self.filter_components_by_type(ty=sys_host.FullSystemHost)) full_sys_hosts = self.filter_components_by_type(ty=sys_host.FullSystemHost)
if len(full_sys_hosts) != 1: if len(full_sys_hosts) != 1:
raise Exception("Gem5Sim only supports simulating 1 FullSystemHost") raise Exception("Gem5Sim only supports simulating 1 FullSystemHost")
cmd = f"{inst.join_repo_base(f"sims/external/gem5/build/X86/gem5.{self.variant}")} --outdir={inst.get_simmulator_output_dir(sim=self)} " cmd = f"{inst.join_repo_base(f"{self._executable}.{self.variant}")} --outdir={inst.get_simmulator_output_dir(sim=self)} "
cmd += " ".join(self.extra_main_args) cmd += " ".join(self.extra_main_args)
cmd += ( cmd += (
f" {inst.join_repo_base("sims/external/gem5/configs/simbricks/simbricks.py")} --caches --l2cache " f" {inst.join_repo_base("sims/external/gem5/configs/simbricks/simbricks.py")} --caches --l2cache "
...@@ -150,7 +152,7 @@ class Gem5Sim(HostSim): ...@@ -150,7 +152,7 @@ class Gem5Sim(HostSim):
continue continue
assert socket._type == inst_base.SockType.CONNECT assert socket._type == inst_base.SockType.CONNECT
cmd += ( cmd += (
f'--simbricks-mem={dev.size}@{dev.addr}@{dev.as_id}@' # TODO: FIXME f'--simbricks-mem={dev._size}@{dev._addr}@{dev._as_id}@' # TODO: FIXME
f'connect:{socket._path}' f'connect:{socket._path}'
f':latency={latency}ns' f':latency={latency}ns'
f':sync_interval={sync_period}ns' f':sync_interval={sync_period}ns'
...@@ -175,28 +177,6 @@ class Gem5Sim(HostSim): ...@@ -175,28 +177,6 @@ class Gem5Sim(HostSim):
cmd += ' '.join(self.extra_config_args) cmd += ' '.join(self.extra_config_args)
return cmd return cmd
for dev in full_sys_hosts[0].ifs: # TODO
if dev == dev.channel.a:
peer_if = dev.channel.b
else:
peer_if = dev.channel.a
peer_sim = self.experiment.find_sim(peer_if)
chn_sim = self.experiment.find_sim(dev.channel)
cmd += (
f"--simbricks-pci=connect:{env.dev_pci_path(peer_sim)}"
f":latency={dev.channel.latency}ns"
f":sync_interval={chn_sim.sync_period}ns"
)
# if cpu_type == 'TimingSimpleCPU' and: #TODO: FIXME
# cmd += ':sync'
cmd += " "
return cmd
def checkpoint_commands(self) -> list[str]:
return ["m5 checkpoint"]
class QemuSim(HostSim): class QemuSim(HostSim):
......
...@@ -33,29 +33,34 @@ class NetSim(sim_base.Simulator): ...@@ -33,29 +33,34 @@ class NetSim(sim_base.Simulator):
"""Base class for network simulators.""" """Base class for network simulators."""
def __init__( def __init__(
self, simulation: sim_base.Simulation, relative_executable_path: str = "" self,
simulation: sim_base.Simulation,
executable: str,
name: str,
) -> None: ) -> None:
super().__init__(simulation, relative_executable_path=relative_executable_path) super().__init__(simulation=simulation, executable=executable, name=name)
def full_name(self) -> str: def full_name(self) -> str:
return "net." + self.name return "net." + self.name
def init_network(self) -> None: def init_network(self) -> None:
pass pass
def supported_socket_types(self) -> set[inst_base.SockType]: def supported_socket_types(self) -> set[inst_base.SockType]:
return [inst_base.SockType.CONNECT] return [inst_base.SockType.CONNECT]
class WireNet(NetSim): class WireNet(NetSim):
def __init__(self, simulation: sim_base.Simulation) -> None: def __init__(
self, simulation: sim_base.Simulation, relative_pcap_filepath: str | None = None
) -> None:
super().__init__( super().__init__(
simulation=simulation, simulation=simulation,
relative_executable_path="/sims/net/wire/net_wire", executable="sims/net/wire/net_wire",
relative_pcap_file_path=None, name=f"WireNet-{self._id}",
) )
self._relative_pcap_file_path: str | None = "relative_pcap_file_path" self._relative_pcap_file_path: str | None = relative_pcap_filepath
def add(self, wire: eth.EthWire): def add(self, wire: eth.EthWire):
base_utils.has_expected_type(wire, eth.EthWire) base_utils.has_expected_type(wire, eth.EthWire)
...@@ -67,15 +72,15 @@ class WireNet(NetSim): ...@@ -67,15 +72,15 @@ class WireNet(NetSim):
def run_cmd(self, inst: inst_base.Instantiation) -> str: def run_cmd(self, inst: inst_base.Instantiation) -> str:
channels = self.get_channels() channels = self.get_channels()
eth_latency, sync_period, sync = ( eth_latency, sync_period, run_sync = (
sim_base.Simulator.get_unique_latency_period_sync(channels=channels) sim_base.Simulator.get_unique_latency_period_sync(channels=channels)
) )
sockets = self._get_sockets(inst=inst) sockets = self._get_sockets(inst=inst)
assert len(sockets) == 2 assert len(sockets) == 2
cmd = inst.join_repo_base(self._relative_executable_path) cmd = inst.join_repo_base(self._executable)
cmd += f"{sockets[0]} {sockets[1]} {run_sync} {sync_period} {eth_latency}" cmd += f"{sockets[0]._path} {sockets[1]._path} {run_sync} {sync_period} {eth_latency}"
if self._relative_pcap_file_path is not None: if self._relative_pcap_file_path is not None:
pcap_file = inst.join_output_base( pcap_file = inst.join_output_base(
...@@ -90,13 +95,15 @@ class SwitchNet(NetSim): ...@@ -90,13 +95,15 @@ class SwitchNet(NetSim):
def __init__( def __init__(
self, self,
simulation: sim_base.Simulation, simulation: sim_base.Simulation,
relative_executable_path="/sims/net/switch/net_switch", executable: str = "sims/net/switch/net_switch",
relative_pcap_file_path=None, relative_pcap_filepath: str | None = None,
) -> None: ) -> None:
super().__init__( super().__init__(
simulation=simulation, relative_executable_path=relative_executable_path simulation=simulation,
executable=executable,
name=f"SwitchNet-{self._id}",
) )
self._relative_pcap_file_path: str | None = relative_pcap_file_path self._relative_pcap_file_path: str | None = relative_pcap_filepath
def add(self, switch_spec: eth.EthSwitch): def add(self, switch_spec: eth.EthSwitch):
base_utils.has_expected_type(switch_spec, eth.EthSwitch) base_utils.has_expected_type(switch_spec, eth.EthSwitch)
...@@ -110,7 +117,7 @@ class SwitchNet(NetSim): ...@@ -110,7 +117,7 @@ class SwitchNet(NetSim):
sim_base.Simulator.get_unique_latency_period_sync(channels=channels) sim_base.Simulator.get_unique_latency_period_sync(channels=channels)
) )
cmd = inst.join_repo_base(self._relative_executable_path) cmd = inst.join_repo_base(self._executable)
cmd += f" -S {sync_period} -E {eth_latency}" cmd += f" -S {sync_period} -E {eth_latency}"
if not run_sync: if not run_sync:
...@@ -141,9 +148,10 @@ class MemSwitchNet(SwitchNet): ...@@ -141,9 +148,10 @@ class MemSwitchNet(SwitchNet):
) -> None: ) -> None:
super().__init__( super().__init__(
simulation=simulation, simulation=simulation,
relative_executable_path="/sims/mem/memswitch/memswitch", executable="sims/mem/memswitch/memswitch",
relative_pcap_file_path=relative_pcap_file_path, relative_pcap_file_path=relative_pcap_file_path,
) )
self._name = f"MemSwitchNet-{self._id}"
"""AS_ID,VADDR_START,VADDR_END,MEMNODE_MAC,PHYS_START.""" """AS_ID,VADDR_START,VADDR_END,MEMNODE_MAC,PHYS_START."""
self.mem_map = [] self.mem_map = []
......
...@@ -20,121 +20,110 @@ ...@@ -20,121 +20,110 @@
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import simbricks.orchestration.system as sys_conf from simbricks.orchestration.system import base as sys_base
import typing as tp from simbricks.orchestration.system import pcie as sys_pcie
from simbricks.orchestration.system import eth as sys_eth
from simbricks.orchestration.system import nic as sys_nic
from simbricks.orchestration.instantiation import base as inst_base from simbricks.orchestration.instantiation import base as inst_base
from simbricks.orchestration.simulation import base from simbricks.orchestration.simulation import sim_base
class PCIDevSim(base.Simulator): class PCIDevSim(sim_base.Simulator):
"""Base class for PCIe device simulators.""" """Base class for PCIe device simulators."""
def __init__(self, e: base.Simulation) -> None: def __init__(
super().__init__(e) self, simulation: sim_base.Simulation, executable: str, name: str
) -> None:
self.start_tick = 0 super().__init__(simulation=simulation, executable=executable, name=name)
"""The timestamp at which to start the simulation. This is useful when
the simulator is only attached at a later point in time and needs to
synchronize with connected simulators. For example, this could be used
when taking checkpoints to only attach certain simulators after the
checkpoint has been taken."""
def full_name(self) -> str: def full_name(self) -> str:
return 'dev.' + self.name return "dev." + self.name
def is_nic(self) -> bool:
return False
def sockets_cleanup(self, inst: inst_base.Instantiation) -> tp.List[str]:
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]:
return [inst_base.Socket(f'{inst._env._workdir}/dev.pci.{self.name}')]
def supported_socket_types(self) -> set[inst_base.SockType]: def supported_socket_types(self) -> set[inst_base.SockType]:
return [inst_base.SockType.LISTEN] return [inst_base.SockType.LISTEN]
class NICSim(PCIDevSim): class NICSim(PCIDevSim):
"""Base class for NIC simulators.""" """Base class for NIC simulators."""
def __init__(self, e: base.Simulation) -> None: def full_name(self) -> str:
super().__init__(e) return "nic." + self.name
self.start_tick = 0
self.name = f'{self._id}'
def add(self, nic: sys_conf.SimplePCIeNIC):
super().add(nic)
def basic_args(self, inst: inst_base.Instantiation, extra: tp.Optional[str] = None) -> str: def __init__(
# TODO: need some fix. how to handle multiple nics in one simulator? self, simulation: sim_base.Simulation, executable: str, name: str
for c in self._components: ) -> None:
nic_comp = c super().__init__(simulation=simulation, executable=executable, name=name)
nic_pci_chan_comp = nic_comp._pci_if.channel
nic_eth_chan_comp = nic_comp._eth_if.channel
nic_pci_chan_sim = self._simulation.retrieve_or_create_channel(nic_pci_chan_comp)
nic_eth_chan_sim = self._simulation.retrieve_or_create_channel(nic_eth_chan_comp)
def add(self, nic: sys_nic.SimplePCIeNIC):
super().add(nic)
cmd = ( def run_cmd(self, inst: inst_base.Instantiation) -> str:
f'{inst._env._workdir}/dev.pci.{self.name} {inst._env._workdir}/nic.eth.{self.name}' channels = self.get_channels()
f' {inst._env._shm_base}/dev.shm.{self.name} {nic_pci_chan_sim._synchronized} {self.start_tick}' latency, sync_period, run_sync = (
f' {nic_pci_chan_sim.sync_period} {nic_pci_chan_comp.latency} {nic_eth_chan_comp.latency}' sim_base.Simulator.get_unique_latency_period_sync(channels=channels)
) )
# if nic_comp.mac is not None:
# cmd += ' ' + (''.join(reversed(nic_comp.mac.split(':'))))
if extra is not None: cmd = f"{inst.join_repo_base(relative_path=self._executable)} "
cmd += ' ' + extra
return cmd
def basic_run_cmd( pci_devices = self.filter_components_by_type(ty=sys_eth.EthSimpleNIC)
self, inst: inst_base.Instantiation, name: str, extra: tp.Optional[str] = None assert len(pci_devices) == 1
) -> str: socket = self._get_socket(inst=inst, interface=pci_devices[0]._eth_if)
cmd = f'{inst._env._repodir}/sims/nic/{name} {self.basic_args(inst, extra)}' assert socket is not None
return cmd cmd += socket._path
def full_name(self) -> str: eth_devices = self.filter_components_by_type(ty=sys_pcie.PCIeSimpleDevice)
return 'nic.' + self.name assert len(eth_devices) == 1
socket = self._get_socket(inst=inst, interface=eth_devices[0]._pci_if)
assert socket is not None
cmd += socket._path
def is_nic(self) -> bool: cmd += (
return True f" {inst.get_simulator_shm_pool_path(sim=self)} {run_sync} {self._start_tick}"
f" {sync_period} {latency} {latency}"
)
# if self.mac is not None: # TODO: FIXME
# cmd += " " + ("".join(reversed(self.mac.split(":"))))
def sockets_cleanup(self, inst: inst_base.Instantiation) -> tp.List[str]: if self.extra_args is not None:
for c in self._components: cmd += " " + self.extra_args
nic_comp = c
return super().sockets_cleanup(inst) + [inst_base.Socket(f'{inst._env._workdir}/nic.eth.{self.name}')]
def sockets_wait(self, inst: inst_base.Instantiation) -> tp.List[str]: return cmd
for c in self._components:
nic_comp = c
return super().sockets_wait(inst) + [inst_base.Socket(f'{inst._env._workdir}/nic.eth.{self.name}')]
class I40eNicSim(NICSim): class I40eNicSim(NICSim):
def __init__(self, e: 'Simulation'): def __init__(self, simulation: sim_base.Simulation):
super().__init__(e) super().__init__(
simulation=simulation,
executable="sims/nic/i40e_bm/i40e_bm",
name=f"NICSim-{self._id}",
)
def run_cmd(self, inst: inst_base.Instantiation) -> str: def run_cmd(self, inst: inst_base.Instantiation) -> str:
return self.basic_run_cmd(inst, '/i40e_bm/i40e_bm') return super().run_cmd(inst=inst)
class CorundumBMNICSim(NICSim): class CorundumBMNICSim(NICSim):
def __init__(self, e: 'Simulation'): def __init__(self, simulation: sim_base.Simulation):
super().__init__(e) super().__init__(
simulation=simulation,
executable="sims/nic/corundum_bm/corundum_bm",
name=f"CorundumBMNICSim-{self._id}",
)
def run_cmd(self, inst: inst_base.Instantiation) -> str: def run_cmd(self, inst: inst_base.Instantiation) -> str:
return self.basic_run_cmd(inst, '/corundum_bm/corundum_bm') return super().run_cmd(inst=inst)
class CorundumVerilatorNICSim(NICSim): class CorundumVerilatorNICSim(NICSim):
def __init__(self, e: 'Simulation'): def __init__(self, simulation: sim_base.Simulation):
super().__init__(e) super().__init__(
simulation=simulation,
executable="sims/nic/corundum/corundum_verilator",
name=f"CorundumVerilatorNICSim-{self._id}",
)
self.clock_freq = 250 # MHz self.clock_freq = 250 # MHz
def resreq_mem(self) -> int: def resreq_mem(self) -> int:
...@@ -142,9 +131,6 @@ class CorundumVerilatorNICSim(NICSim): ...@@ -142,9 +131,6 @@ class CorundumVerilatorNICSim(NICSim):
return 512 return 512
def run_cmd(self, inst: inst_base.Instantiation) -> str: def run_cmd(self, inst: inst_base.Instantiation) -> str:
print("run cmd") cmd = super().run_cmd(inst=inst)
print(self.basic_run_cmd(inst, '/corundum/corundum_verilator')) cmd += str(self.clock_freq)
return cmd
return self.basic_run_cmd(
inst, '/corundum/corundum_verilator', str(self.clock_freq)
)
...@@ -57,6 +57,9 @@ class MemSimpleDevice(base.Component): ...@@ -57,6 +57,9 @@ class MemSimpleDevice(base.Component):
def __init__(self, s: base.System): def __init__(self, s: base.System):
super().__init__(s) super().__init__(s)
self._mem_if: MemDeviceInterface = MemDeviceInterface(c=self) self._mem_if: MemDeviceInterface = MemDeviceInterface(c=self)
self._addr = 0xe000000000000000
self._size = 1024 * 1024 * 1024 # 1GB
self._as_id = 0
def interfaces(self) -> list[base.Interface]: def interfaces(self) -> list[base.Interface]:
return [self._mem_if] return [self._mem_if]
......
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