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):
dir_path = f"output.{sim.full_name()}-{sim._id}"
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:
return self._join_paths(
base=self._env._output_base,
......
......@@ -49,17 +49,32 @@ class Simulator(utils_base.IdObj):
def __init__(
self,
simulation: sim_base.Simulation,
executable: str,
name: str = "",
relative_executable_path: str = "",
) -> None:
super().__init__()
self.name: str = name
self._relative_executable_path: str = relative_executable_path
self._executable = executable
self._simulation: sim_base.Simulation = simulation
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)
@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
def filter_sockets(
sockets: list[inst_base.Socket],
......@@ -98,13 +113,19 @@ class Simulator(utils_base.IdObj):
raise Exception("could not determine eth_latency and sync_period")
return latency, sync_period, run_sync
T = tp.TypeVar("T")
def filter_components_by_pred(
self, pred: tp.Callable[[sys_conf.Component], bool]
) -> list[sys_conf.Component]:
self,
pred: tp.Callable[[sys_conf.Component], bool],
ty: type[T] = sys_conf.Component,
) -> list[T]:
return list(filter(pred, self._components))
def filter_components_by_type(self, ty) -> list[sys_conf.Component]:
return self.filter_components_by_pred(lambda comp: isinstance(comp, ty))
def filter_components_by_type(self, ty: type[T]) -> list[T]:
return self.filter_components_by_pred(
pred=lambda comp: isinstance(comp, ty), ty=ty
)
def components(self) -> set[sys_conf.Component]:
return self._components
......
......@@ -38,8 +38,8 @@ if tp.TYPE_CHECKING:
class HostSim(sim_base.Simulator):
def __init__(self, simulation: sim_base.Simulation, name=""):
super().__init__(simulation=simulation, name=name)
def __init__(self, simulation: sim_base.Simulation, executable: str, name=""):
super().__init__(simulation=simulation, executable=executable, name=name)
def full_name(self) -> str:
return "host." + self.name
......@@ -60,13 +60,12 @@ class HostSim(sim_base.Simulator):
class Gem5Sim(HostSim):
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 = "TimingSimpleCPU"
self.extra_main_args: list[str] = []
self.extra_config_args: list[str] = []
self.variant = "fast"
self.wait = True
def resreq_cores(self) -> int:
return 1
......@@ -86,16 +85,19 @@ class Gem5Sim(HostSim):
)
await task
def checkpoint_commands(self) -> list[str]:
return ["m5 checkpoint"]
def run_cmd(self, inst: inst_base.Instantiation) -> str:
cpu_type = self.cpu_type
if inst.create_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:
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 += (
f" {inst.join_repo_base("sims/external/gem5/configs/simbricks/simbricks.py")} --caches --l2cache "
......@@ -150,7 +152,7 @@ class Gem5Sim(HostSim):
continue
assert socket._type == inst_base.SockType.CONNECT
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':latency={latency}ns'
f':sync_interval={sync_period}ns'
......@@ -175,28 +177,6 @@ class Gem5Sim(HostSim):
cmd += ' '.join(self.extra_config_args)
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):
......
......@@ -33,9 +33,12 @@ class NetSim(sim_base.Simulator):
"""Base class for network simulators."""
def __init__(
self, simulation: sim_base.Simulation, relative_executable_path: str = ""
self,
simulation: sim_base.Simulation,
executable: str,
name: str,
) -> None:
super().__init__(simulation, relative_executable_path=relative_executable_path)
super().__init__(simulation=simulation, executable=executable, name=name)
def full_name(self) -> str:
return "net." + self.name
......@@ -49,13 +52,15 @@ class NetSim(sim_base.Simulator):
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__(
simulation=simulation,
relative_executable_path="/sims/net/wire/net_wire",
relative_pcap_file_path=None,
executable="sims/net/wire/net_wire",
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):
base_utils.has_expected_type(wire, eth.EthWire)
......@@ -67,15 +72,15 @@ class WireNet(NetSim):
def run_cmd(self, inst: inst_base.Instantiation) -> str:
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)
)
sockets = self._get_sockets(inst=inst)
assert len(sockets) == 2
cmd = inst.join_repo_base(self._relative_executable_path)
cmd += f"{sockets[0]} {sockets[1]} {run_sync} {sync_period} {eth_latency}"
cmd = inst.join_repo_base(self._executable)
cmd += f"{sockets[0]._path} {sockets[1]._path} {run_sync} {sync_period} {eth_latency}"
if self._relative_pcap_file_path is not None:
pcap_file = inst.join_output_base(
......@@ -90,13 +95,15 @@ class SwitchNet(NetSim):
def __init__(
self,
simulation: sim_base.Simulation,
relative_executable_path="/sims/net/switch/net_switch",
relative_pcap_file_path=None,
executable: str = "sims/net/switch/net_switch",
relative_pcap_filepath: str | None = None,
) -> None:
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):
base_utils.has_expected_type(switch_spec, eth.EthSwitch)
......@@ -110,7 +117,7 @@ class SwitchNet(NetSim):
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}"
if not run_sync:
......@@ -141,9 +148,10 @@ class MemSwitchNet(SwitchNet):
) -> None:
super().__init__(
simulation=simulation,
relative_executable_path="/sims/mem/memswitch/memswitch",
executable="sims/mem/memswitch/memswitch",
relative_pcap_file_path=relative_pcap_file_path,
)
self._name = f"MemSwitchNet-{self._id}"
"""AS_ID,VADDR_START,VADDR_END,MEMNODE_MAC,PHYS_START."""
self.mem_map = []
......
......@@ -20,121 +20,110 @@
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import simbricks.orchestration.system as sys_conf
import typing as tp
from simbricks.orchestration.system import base as sys_base
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.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."""
def __init__(self, e: base.Simulation) -> None:
super().__init__(e)
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."""
def __init__(
self, simulation: sim_base.Simulation, executable: str, name: str
) -> None:
super().__init__(simulation=simulation, executable=executable, name=name)
def full_name(self) -> str:
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}')]
return "dev." + self.name
def supported_socket_types(self) -> set[inst_base.SockType]:
return [inst_base.SockType.LISTEN]
class NICSim(PCIDevSim):
"""Base class for NIC simulators."""
def __init__(self, e: base.Simulation) -> None:
super().__init__(e)
self.start_tick = 0
self.name = f'{self._id}'
def add(self, nic: sys_conf.SimplePCIeNIC):
super().add(nic)
def full_name(self) -> str:
return "nic." + self.name
def basic_args(self, inst: inst_base.Instantiation, extra: tp.Optional[str] = None) -> str:
# TODO: need some fix. how to handle multiple nics in one simulator?
for c in self._components:
nic_comp = c
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 __init__(
self, simulation: sim_base.Simulation, executable: str, name: str
) -> None:
super().__init__(simulation=simulation, executable=executable, name=name)
def add(self, nic: sys_nic.SimplePCIeNIC):
super().add(nic)
cmd = (
f'{inst._env._workdir}/dev.pci.{self.name} {inst._env._workdir}/nic.eth.{self.name}'
f' {inst._env._shm_base}/dev.shm.{self.name} {nic_pci_chan_sim._synchronized} {self.start_tick}'
f' {nic_pci_chan_sim.sync_period} {nic_pci_chan_comp.latency} {nic_eth_chan_comp.latency}'
def run_cmd(self, inst: inst_base.Instantiation) -> str:
channels = self.get_channels()
latency, sync_period, run_sync = (
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 += ' ' + extra
return cmd
cmd = f"{inst.join_repo_base(relative_path=self._executable)} "
def basic_run_cmd(
self, inst: inst_base.Instantiation, name: str, extra: tp.Optional[str] = None
) -> str:
cmd = f'{inst._env._repodir}/sims/nic/{name} {self.basic_args(inst, extra)}'
return cmd
pci_devices = self.filter_components_by_type(ty=sys_eth.EthSimpleNIC)
assert len(pci_devices) == 1
socket = self._get_socket(inst=inst, interface=pci_devices[0]._eth_if)
assert socket is not None
cmd += socket._path
def full_name(self) -> str:
return 'nic.' + self.name
eth_devices = self.filter_components_by_type(ty=sys_pcie.PCIeSimpleDevice)
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
cmd += (
f" {inst.get_simulator_shm_pool_path(sim=self)} {run_sync} {self._start_tick}"
f" {sync_period} {latency} {latency}"
)
def is_nic(self) -> bool:
return True
# 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]:
for c in self._components:
nic_comp = c
return super().sockets_cleanup(inst) + [inst_base.Socket(f'{inst._env._workdir}/nic.eth.{self.name}')]
if self.extra_args is not None:
cmd += " " + self.extra_args
def sockets_wait(self, inst: inst_base.Instantiation) -> tp.List[str]:
for c in self._components:
nic_comp = c
return super().sockets_wait(inst) + [inst_base.Socket(f'{inst._env._workdir}/nic.eth.{self.name}')]
return cmd
class I40eNicSim(NICSim):
def __init__(self, e: 'Simulation'):
super().__init__(e)
def __init__(self, simulation: sim_base.Simulation):
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:
return self.basic_run_cmd(inst, '/i40e_bm/i40e_bm')
return super().run_cmd(inst=inst)
class CorundumBMNICSim(NICSim):
def __init__(self, e: 'Simulation'):
super().__init__(e)
def __init__(self, simulation: sim_base.Simulation):
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:
return self.basic_run_cmd(inst, '/corundum_bm/corundum_bm')
return super().run_cmd(inst=inst)
class CorundumVerilatorNICSim(NICSim):
def __init__(self, e: 'Simulation'):
super().__init__(e)
def __init__(self, simulation: sim_base.Simulation):
super().__init__(
simulation=simulation,
executable="sims/nic/corundum/corundum_verilator",
name=f"CorundumVerilatorNICSim-{self._id}",
)
self.clock_freq = 250 # MHz
def resreq_mem(self) -> int:
......@@ -142,9 +131,6 @@ class CorundumVerilatorNICSim(NICSim):
return 512
def run_cmd(self, inst: inst_base.Instantiation) -> str:
print("run cmd")
print(self.basic_run_cmd(inst, '/corundum/corundum_verilator'))
return self.basic_run_cmd(
inst, '/corundum/corundum_verilator', str(self.clock_freq)
)
cmd = super().run_cmd(inst=inst)
cmd += str(self.clock_freq)
return cmd
......@@ -57,6 +57,9 @@ class MemSimpleDevice(base.Component):
def __init__(self, s: base.System):
super().__init__(s)
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]:
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