Merge remote-tracking branch 'origin/dev' into gapbs
This commit is contained in:
commit
911577c674
|
@ -72,6 +72,8 @@ class FireSimLink(object):
|
|||
""" Return True if the user has mapped the two endpoints of this link to
|
||||
separate hosts. This implies a SocketServerPort / SocketClientPort will be used
|
||||
to implement the Link. If False, use a sharedmem port to implement the link. """
|
||||
if type(self.get_downlink_side()) == FireSimDummyServerNode:
|
||||
return False
|
||||
return self.get_uplink_side().host_instance != self.get_downlink_side().host_instance
|
||||
|
||||
def get_global_link_id(self):
|
||||
|
@ -249,12 +251,12 @@ class FireSimServerNode(FireSimNode):
|
|||
an array. """
|
||||
all_paths = []
|
||||
# todo handle none case
|
||||
all_paths.append(self.get_job().rootfs_path())
|
||||
all_paths.append(self.get_job().bootbinary_path())
|
||||
all_paths.append([self.get_job().rootfs_path(), ''])
|
||||
all_paths.append([self.get_job().bootbinary_path(), ''])
|
||||
|
||||
all_paths.append(self.server_hardware_config.get_local_driver_path())
|
||||
all_paths.append(self.server_hardware_config.get_local_runtime_conf_path())
|
||||
all_paths.append(self.server_hardware_config.get_local_assert_def_path())
|
||||
all_paths.append([self.server_hardware_config.get_local_driver_path(), ''])
|
||||
all_paths.append([self.server_hardware_config.get_local_runtime_conf_path(), ''])
|
||||
all_paths.append([self.server_hardware_config.get_local_assert_def_path(), ''])
|
||||
return all_paths
|
||||
|
||||
def get_agfi(self):
|
||||
|
@ -272,13 +274,164 @@ class FireSimServerNode(FireSimNode):
|
|||
def get_job_name(self):
|
||||
return self.job.jobname
|
||||
|
||||
def get_rootfs_name(self):
|
||||
def get_rootfs_name(self, dummyindex=0):
|
||||
if dummyindex:
|
||||
return self.get_job().rootfs_path().split("/")[-1] + "-" + str(dummyindex)
|
||||
return self.get_job().rootfs_path().split("/")[-1]
|
||||
|
||||
def get_bootbin_name(self):
|
||||
def get_bootbin_name(self, dummyindex=0):
|
||||
if dummyindex:
|
||||
return self.get_job().bootbinary_path().split("/")[-1] + "-" + str(dummyindex)
|
||||
return self.get_job().bootbinary_path().split("/")[-1]
|
||||
|
||||
|
||||
class FireSimSuperNodeServerNode(FireSimServerNode):
|
||||
""" This is the main server node for supernode mode. This knows how to
|
||||
call out to dummy server nodes to get all the info to launch the one
|
||||
command line to run the FPGA sim that has N > 1 sims on one fpga.
|
||||
|
||||
TODO: this is currently hardcoded to N=4"""
|
||||
|
||||
def supernode_get_sibling(self, siblingindex):
|
||||
""" return the sibling for supernode mode.
|
||||
siblingindex = 1 -> next sibling, 2 = second, 3 = last one."""
|
||||
for index, servernode in enumerate(map( lambda x : x.get_downlink_side(), self.uplinks[0].get_uplink_side().downlinks)):
|
||||
if self == servernode:
|
||||
return self.uplinks[0].get_uplink_side().downlinks[index+siblingindex].get_downlink_side()
|
||||
|
||||
def supernode_get_sibling_mac_address(self, siblingindex):
|
||||
""" return the sibling's mac address for supernode mode.
|
||||
siblingindex = 1 -> next sibling, 2 = second, 3 = last one."""
|
||||
return self.supernode_get_sibling(siblingindex).get_mac_address()
|
||||
|
||||
def supernode_get_sibling_rootfs(self, siblingindex):
|
||||
""" return the sibling's rootfs for supernode mode.
|
||||
siblingindex = 1 -> next sibling, 2 = second, 3 = last one."""
|
||||
return self.supernode_get_sibling(siblingindex).get_rootfs_name(siblingindex)
|
||||
|
||||
def supernode_get_sibling_bootbin(self, siblingindex):
|
||||
""" return the sibling's rootfs for supernode mode.
|
||||
siblingindex = 1 -> next sibling, 2 = second, 3 = last one."""
|
||||
return self.supernode_get_sibling(siblingindex).get_bootbin_name(siblingindex)
|
||||
|
||||
def supernode_get_sibling_rootfs_path(self, siblingindex):
|
||||
return self.supernode_get_sibling(siblingindex).get_job().rootfs_path()
|
||||
|
||||
def supernode_get_sibling_bootbinary_path(self, siblingindex):
|
||||
return self.supernode_get_sibling(siblingindex).get_job().bootbinary_path()
|
||||
|
||||
def supernode_get_sibling_link_latency(self, siblingindex):
|
||||
return self.supernode_get_sibling(siblingindex).server_link_latency
|
||||
|
||||
def supernode_get_sibling_bw_max(self, siblingindex):
|
||||
return self.supernode_get_sibling(siblingindex).server_bw_max
|
||||
|
||||
def supernode_get_sibling_shmemportname(self, siblingindex):
|
||||
return self.supernode_get_sibling(siblingindex).uplinks[0].get_global_link_id()
|
||||
|
||||
def get_sim_start_command(self, slotno):
|
||||
""" return the command to start the simulation. assumes it will be
|
||||
called in a directory where its required_files are already located.
|
||||
|
||||
Currently hardcoded to 4 nodes.
|
||||
"""
|
||||
sibling1mac = self.supernode_get_sibling_mac_address(1)
|
||||
sibling2mac = self.supernode_get_sibling_mac_address(2)
|
||||
sibling3mac = self.supernode_get_sibling_mac_address(3)
|
||||
|
||||
sibling1root = self.supernode_get_sibling_rootfs(1)
|
||||
sibling2root = self.supernode_get_sibling_rootfs(2)
|
||||
sibling3root = self.supernode_get_sibling_rootfs(3)
|
||||
|
||||
sibling1bootbin = self.supernode_get_sibling_bootbin(1)
|
||||
sibling2bootbin = self.supernode_get_sibling_bootbin(2)
|
||||
sibling3bootbin = self.supernode_get_sibling_bootbin(3)
|
||||
|
||||
sibling1link_latency = self.supernode_get_sibling_link_latency(1)
|
||||
sibling2link_latency = self.supernode_get_sibling_link_latency(2)
|
||||
sibling3link_latency = self.supernode_get_sibling_link_latency(3)
|
||||
|
||||
sibling1bw_max = self.supernode_get_sibling_bw_max(1)
|
||||
sibling2bw_max = self.supernode_get_sibling_bw_max(2)
|
||||
sibling3bw_max = self.supernode_get_sibling_bw_max(3)
|
||||
|
||||
shmemportname0 = "default"
|
||||
shmemportname1 = "default"
|
||||
shmemportname2 = "default"
|
||||
shmemportname3 = "default"
|
||||
|
||||
if self.uplinks:
|
||||
shmemportname0 = self.uplinks[0].get_global_link_id()
|
||||
shmemportname1 = self.supernode_get_sibling_shmemportname(1)
|
||||
shmemportname2 = self.supernode_get_sibling_shmemportname(2)
|
||||
shmemportname3 = self.supernode_get_sibling_shmemportname(3)
|
||||
|
||||
return self.server_hardware_config.get_supernode_boot_simulation_command(
|
||||
slotno,
|
||||
self.get_mac_address(), sibling1mac, sibling2mac, sibling3mac,
|
||||
self.get_rootfs_name(), sibling1root, sibling2root, sibling3root,
|
||||
self.server_link_latency, sibling1link_latency, sibling2link_latency, sibling3link_latency,
|
||||
self.server_bw_max, sibling1bw_max, sibling2bw_max, sibling3bw_max,
|
||||
self.server_profile_interval,
|
||||
self.get_bootbin_name(), sibling1bootbin, sibling2bootbin, sibling3bootbin,
|
||||
self.trace_enable, self.trace_start, self.trace_end,
|
||||
shmemportname0, shmemportname1, shmemportname2, shmemportname3)
|
||||
|
||||
def get_required_files_local_paths(self):
|
||||
""" Return local paths of all stuff needed to run this simulation as
|
||||
an array. """
|
||||
|
||||
def get_path_trailing(filepath):
|
||||
return filepath.split("/")[-1]
|
||||
def local_and_remote(filepath, index):
|
||||
return [filepath, get_path_trailing(filepath) + str(index)]
|
||||
|
||||
all_paths = []
|
||||
# todo handle none case
|
||||
all_paths.append([self.get_job().rootfs_path(),
|
||||
self.get_rootfs_name()])
|
||||
all_paths.append([self.supernode_get_sibling_rootfs_path(1),
|
||||
self.supernode_get_sibling_rootfs(1)])
|
||||
all_paths.append([self.supernode_get_sibling_rootfs_path(2),
|
||||
self.supernode_get_sibling_rootfs(2)])
|
||||
all_paths.append([self.supernode_get_sibling_rootfs_path(3),
|
||||
self.supernode_get_sibling_rootfs(3)])
|
||||
|
||||
|
||||
all_paths.append([self.get_job().bootbinary_path(),
|
||||
self.get_bootbin_name()])
|
||||
all_paths.append([self.supernode_get_sibling_bootbinary_path(1),
|
||||
self.supernode_get_sibling_bootbin(1)])
|
||||
all_paths.append([self.supernode_get_sibling_bootbinary_path(2),
|
||||
self.supernode_get_sibling_bootbin(2)])
|
||||
all_paths.append([self.supernode_get_sibling_bootbinary_path(3),
|
||||
self.supernode_get_sibling_bootbin(3)])
|
||||
|
||||
all_paths.append([self.server_hardware_config.get_local_driver_path(), ''])
|
||||
all_paths.append([self.server_hardware_config.get_local_runtime_conf_path(), ''])
|
||||
all_paths.append([self.server_hardware_config.get_local_assert_def_path(), ''])
|
||||
return all_paths
|
||||
|
||||
def get_rootfs_name(self, dummyindex=0):
|
||||
if dummyindex:
|
||||
return self.get_job().rootfs_path().split("/")[-1] + "-" + str(dummyindex)
|
||||
return self.get_job().rootfs_path().split("/")[-1]
|
||||
|
||||
def get_bootbin_name(self, dummyindex=0):
|
||||
if dummyindex:
|
||||
return self.get_job().bootbinary_path().split("/")[-1] + "-" + str(dummyindex)
|
||||
return self.get_job().bootbinary_path().split("/")[-1]
|
||||
|
||||
|
||||
class FireSimDummyServerNode(FireSimServerNode):
|
||||
""" This is a dummy server node for supernode mode. """
|
||||
def __init__(self, server_hardware_config=None, server_link_latency=None,
|
||||
server_bw_max=None):
|
||||
super(FireSimDummyServerNode, self).__init__(server_hardware_config,
|
||||
server_link_latency,
|
||||
server_bw_max)
|
||||
|
||||
|
||||
class FireSimSwitchNode(FireSimNode):
|
||||
""" This is a simulated switch instance in FireSim.
|
||||
|
||||
|
|
|
@ -162,7 +162,6 @@ class FireSimTopologyWithPasses:
|
|||
return
|
||||
assert serverind == len(servers), "ERR: all servers were not assigned to a host."
|
||||
|
||||
|
||||
def pass_simple_networked_host_node_mapping(self):
|
||||
""" A very simple host mapping strategy. """
|
||||
switches = self.firesimtopol.get_dfs_order_switches()
|
||||
|
@ -171,14 +170,17 @@ class FireSimTopologyWithPasses:
|
|||
m4_16s_used = 0
|
||||
|
||||
for switch in switches:
|
||||
downlinknodes = map(lambda x: x.get_downlink_side(), switch.downlinks)
|
||||
# Filter out FireSimDummyServerNodes for actually deploying.
|
||||
# Infrastructure after this point will automatically look at the
|
||||
# FireSimDummyServerNodes if a FireSimSuperNodeServerNode is used
|
||||
downlinknodes = map(lambda x: x.get_downlink_side(), [downlink for downlink in switch.downlinks if not isinstance(downlink.get_downlink_side(), FireSimDummyServerNode)])
|
||||
if all([isinstance(x, FireSimSwitchNode) for x in downlinknodes]):
|
||||
# all downlinks are switches
|
||||
self.run_farm.m4_16s[m4_16s_used].add_switch(switch)
|
||||
m4_16s_used += 1
|
||||
elif all([isinstance(x, FireSimServerNode) for x in downlinknodes]):
|
||||
# all downlinks are simulations
|
||||
if (len(switch.downlinks) == 1) and (f1_2s_used < len(self.run_farm.f1_2s)):
|
||||
if (len(downlinknodes) == 1) and (f1_2s_used < len(self.run_farm.f1_2s)):
|
||||
self.run_farm.f1_2s[f1_2s_used].add_switch(switch)
|
||||
self.run_farm.f1_2s[f1_2s_used].add_simulation(downlinknodes[0])
|
||||
f1_2s_used += 1
|
||||
|
|
|
@ -417,9 +417,10 @@ class InstanceDeployManager:
|
|||
|
||||
files_to_copy = serv.get_required_files_local_paths()
|
||||
for filename in files_to_copy:
|
||||
# here, filename is a pair of (local path, remote path)
|
||||
with StreamLogger('stdout'), StreamLogger('stderr'):
|
||||
# -z --inplace
|
||||
rsync_cap = rsync_project(local_dir=filename, remote_dir=remote_sim_rsync_dir,
|
||||
rsync_cap = rsync_project(local_dir=filename[0], remote_dir=remote_sim_rsync_dir + '/' + filename[1],
|
||||
ssh_opts="-o StrictHostKeyChecking=no", extra_opts="-L", capture=True)
|
||||
rootLogger.debug(rsync_cap)
|
||||
rootLogger.debug(rsync_cap.stderr)
|
||||
|
|
|
@ -100,7 +100,7 @@ class RuntimeHWConfig:
|
|||
# the sed is in there to get rid of newlines in runtime confs
|
||||
driver = self.get_local_driver_binaryname()
|
||||
runtimeconf = self.get_local_runtimeconf_binaryname()
|
||||
basecommand = """screen -S fsim{slotid} -d -m bash -c "script -f -c 'stty intr ^] && sudo ./{driver} +permissive $(sed \':a;N;$!ba;s/\\n/ /g\' {runtimeconf}) +macaddr0={macaddr} +blkdev0={blkdev} +slotid={slotid} +niclog0=niclog {tracefile} +trace-start0={trace_start} +trace-end0={trace_end} +linklatency0={linklatency} +netbw0={netbw} +profile-interval=-1 +profile-interval={profile_interval} +zero-out-dram +shmemportname0={shmemportname} +permissive-off {bootbin} && stty intr ^c' uartlog"; sleep 1""".format(
|
||||
basecommand = """screen -S fsim{slotid} -d -m bash -c "script -f -c 'stty intr ^] && sudo ./{driver} +permissive $(sed \':a;N;$!ba;s/\\n/ /g\' {runtimeconf}) +macaddr0={macaddr} +blkdev0={blkdev} +slotid={slotid} +niclog0=niclog {tracefile} +trace-start0={trace_start} +trace-end0={trace_end} +linklatency0={linklatency} +netbw0={netbw} +profile-interval={profile_interval} +zero-out-dram +shmemportname0={shmemportname} +permissive-off +prog0={bootbin} && stty intr ^c' uartlog"; sleep 1""".format(
|
||||
slotid=slotid, driver=driver, runtimeconf=runtimeconf,
|
||||
macaddr=macaddr, blkdev=blkdev, linklatency=linklatency,
|
||||
netbw=netbw, profile_interval=profile_interval,
|
||||
|
@ -109,6 +109,51 @@ class RuntimeHWConfig:
|
|||
|
||||
return basecommand
|
||||
|
||||
|
||||
def get_supernode_boot_simulation_command(self,
|
||||
slotid,
|
||||
macaddr0, macaddr1,
|
||||
macaddr2, macaddr3,
|
||||
blkdev0, blkdev1,
|
||||
blkdev2, blkdev3,
|
||||
linklatency0, linklatency1,
|
||||
linklatency2, linklatency3,
|
||||
netbw0, netbw1, netbw2, netbw3,
|
||||
profile_interval,
|
||||
bootbin0, bootbin1,
|
||||
bootbin2, bootbin3,
|
||||
trace_enable, trace_start,
|
||||
trace_end,
|
||||
shmemportname0, shmemportname1,
|
||||
shmemportname2, shmemportname3):
|
||||
""" return the command used to boot the simulation. this has to have
|
||||
some external params passed to it, because not everything is contained
|
||||
in a runtimehwconfig. TODO: maybe runtimehwconfig should be renamed to
|
||||
pre-built runtime config? It kinda contains a mix of pre-built and
|
||||
runtime parameters currently. """
|
||||
|
||||
tracefile = "+tracefile0=TRACEFILE" if trace_enable else ""
|
||||
|
||||
# this monstrosity boots the simulator, inside screen, inside script
|
||||
# the sed is in there to get rid of newlines in runtime confs
|
||||
driver = self.get_local_driver_binaryname()
|
||||
runtimeconf = self.get_local_runtimeconf_binaryname()
|
||||
basecommand = """screen -S fsim{slotid} -d -m bash -c "script -f -c 'stty intr ^] && sudo ./{driver} +permissive $(sed \':a;N;$!ba;s/\\n/ /g\' {runtimeconf}) +macaddr0={macaddr0} +macaddr1={macaddr1} +macaddr2={macaddr2} +macaddr3={macaddr3} +blkdev0={blkdev0} +blkdev1={blkdev1} +blkdev2={blkdev2} +blkdev3={blkdev3} +slotid={slotid} +niclog0=niclog {tracefile} +trace-start0={trace_start} +trace-end0={trace_end} +linklatency0={linklatency0} +linklatency1={linklatency1} +linklatency2={linklatency2} +linklatency3={linklatency3} +netbw0={netbw0} +netbw1={netbw1} +netbw2={netbw2} +netbw3={netbw3} +profile-interval={profile_interval} +zero-out-dram +shmemportname0={shmemportname0} +shmemportname1={shmemportname1} +shmemportname2={shmemportname2} +shmemportname3={shmemportname3} +permissive-off +prog0={bootbin0} +prog1={bootbin1} +prog2={bootbin2} +prog3={bootbin3} && stty intr ^c' uartlog"; sleep 1""".format(
|
||||
slotid=slotid, driver=driver, runtimeconf=runtimeconf,
|
||||
macaddr0=macaddr0, macaddr1=macaddr1,macaddr2=macaddr2,macaddr3=macaddr3,
|
||||
blkdev0=blkdev0, blkdev1=blkdev1, blkdev2=blkdev2, blkdev3=blkdev3,
|
||||
linklatency0=linklatency0, linklatency1=linklatency1,
|
||||
linklatency2=linklatency2, linklatency3=linklatency3,
|
||||
netbw0=netbw0, netbw1=netbw1, netbw2=netbw2, netbw3=netbw3,
|
||||
profile_interval=profile_interval,
|
||||
shmemportname0=shmemportname0, shmemportname1=shmemportname1, shmemportname2=shmemportname2, shmemportname3=shmemportname3,
|
||||
bootbin0=bootbin0, bootbin1=bootbin1, bootbin2=bootbin2, bootbin3=bootbin3, tracefile=tracefile,
|
||||
trace_start=trace_start, trace_end=trace_end)
|
||||
|
||||
return basecommand
|
||||
|
||||
|
||||
|
||||
def get_kill_simulation_command(self):
|
||||
driver = self.get_local_driver_binaryname()
|
||||
return """sudo pkill -SIGKILL {driver}""".format(driver=driver)
|
||||
|
|
|
@ -120,8 +120,6 @@ class UserTopologies(object):
|
|||
|
||||
self.custom_mapper = custom_mapper
|
||||
|
||||
|
||||
|
||||
def example_multilink(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
midswitch = FireSimSwitchNode()
|
||||
|
@ -155,7 +153,6 @@ class UserTopologies(object):
|
|||
midswitches[0].add_downlinks([servers[0]])
|
||||
midswitches[1].add_downlinks([servers[1]])
|
||||
|
||||
|
||||
def small_hierarchy_8sims(self):
|
||||
self.custom_mapper = 'mapping_use_one_f1_16xlarge'
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
|
@ -165,7 +162,6 @@ class UserTopologies(object):
|
|||
for swno in range(len(midlevel)):
|
||||
midlevel[swno].add_downlinks(servers[swno])
|
||||
|
||||
|
||||
def small_hierarchy_2sims(self):
|
||||
self.custom_mapper = 'mapping_use_one_f1_16xlarge'
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
|
@ -175,7 +171,6 @@ class UserTopologies(object):
|
|||
for swno in range(len(midlevel)):
|
||||
midlevel[swno].add_downlinks(servers[swno])
|
||||
|
||||
|
||||
def example_1config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
servers = [FireSimServerNode() for y in range(1)]
|
||||
|
@ -259,6 +254,93 @@ class UserTopologies(object):
|
|||
for switchno in range(len(level2switches[switchgroupno])):
|
||||
level2switches[switchgroupno][switchno].add_downlinks(servers[switchgroupno][switchno])
|
||||
|
||||
@staticmethod
|
||||
def supernode_flatten(arr):
|
||||
res = []
|
||||
for x in arr:
|
||||
res = res + x
|
||||
return res
|
||||
|
||||
def supernode_example_4config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
servers = [FireSimSuperNodeServerNode()] + [FireSimDummyServerNode() for x in range(3)]
|
||||
self.roots[0].add_downlinks(servers)
|
||||
def supernode_example_8config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
servers = UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(2)])
|
||||
self.roots[0].add_downlinks(servers)
|
||||
def supernode_example_16config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
servers = UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(4)])
|
||||
self.roots[0].add_downlinks(servers)
|
||||
def supernode_example_32config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
servers = UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(8)])
|
||||
self.roots[0].add_downlinks(servers)
|
||||
|
||||
def supernode_example_64config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
level2switches = [FireSimSwitchNode() for x in range(2)]
|
||||
servers = [UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(8)]) for x in range(2)]
|
||||
for root in self.roots:
|
||||
root.add_downlinks(level2switches)
|
||||
for l2switchNo in range(len(level2switches)):
|
||||
level2switches[l2switchNo].add_downlinks(servers[l2switchNo])
|
||||
|
||||
def supernode_example_128config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
level2switches = [FireSimSwitchNode() for x in range(4)]
|
||||
servers = [UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(8)]) for x in range(4)]
|
||||
for root in self.roots:
|
||||
root.add_downlinks(level2switches)
|
||||
for l2switchNo in range(len(level2switches)):
|
||||
level2switches[l2switchNo].add_downlinks(servers[l2switchNo])
|
||||
|
||||
def supernode_example_256config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
level2switches = [FireSimSwitchNode() for x in range(8)]
|
||||
servers = [UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(8)]) for x in range(8)]
|
||||
for root in self.roots:
|
||||
root.add_downlinks(level2switches)
|
||||
for l2switchNo in range(len(level2switches)):
|
||||
level2switches[l2switchNo].add_downlinks(servers[l2switchNo])
|
||||
|
||||
def supernode_example_512config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
level1switches = [FireSimSwitchNode() for x in range(2)]
|
||||
level2switches = [[FireSimSwitchNode() for x in range(8)] for x in range(2)]
|
||||
servers = [[UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(8)]) for x in range(8)] for x in range(2)]
|
||||
self.roots[0].add_downlinks(level1switches)
|
||||
for switchno in range(len(level1switches)):
|
||||
level1switches[switchno].add_downlinks(level2switches[switchno])
|
||||
for switchgroupno in range(len(level2switches)):
|
||||
for switchno in range(len(level2switches[switchgroupno])):
|
||||
level2switches[switchgroupno][switchno].add_downlinks(servers[switchgroupno][switchno])
|
||||
|
||||
def supernode_example_1024config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
level1switches = [FireSimSwitchNode() for x in range(4)]
|
||||
level2switches = [[FireSimSwitchNode() for x in range(8)] for x in range(4)]
|
||||
servers = [[UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(8)]) for x in range(8)] for x in range(4)]
|
||||
self.roots[0].add_downlinks(level1switches)
|
||||
for switchno in range(len(level1switches)):
|
||||
level1switches[switchno].add_downlinks(level2switches[switchno])
|
||||
for switchgroupno in range(len(level2switches)):
|
||||
for switchno in range(len(level2switches[switchgroupno])):
|
||||
level2switches[switchgroupno][switchno].add_downlinks(servers[switchgroupno][switchno])
|
||||
|
||||
def supernode_example_deep64config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
level1switches = [FireSimSwitchNode() for x in range(2)]
|
||||
level2switches = [[FireSimSwitchNode() for x in range(1)] for x in range(2)]
|
||||
servers = [[UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(8)]) for x in range(1)] for x in range(2)]
|
||||
self.roots[0].add_downlinks(level1switches)
|
||||
for switchno in range(len(level1switches)):
|
||||
level1switches[switchno].add_downlinks(level2switches[switchno])
|
||||
for switchgroupno in range(len(level2switches)):
|
||||
for switchno in range(len(level2switches[switchgroupno])):
|
||||
level2switches[switchgroupno][switchno].add_downlinks(servers[switchgroupno][switchno])
|
||||
|
||||
def dual_example_8config(self):
|
||||
""" two separate 8-node clusters for experiments, e.g. memcached mutilate. """
|
||||
self.roots = [FireSimSwitchNode(), FireSimSwitchNode()]
|
||||
|
@ -279,3 +361,4 @@ class UserTopologies(object):
|
|||
|
||||
def no_net_config(self):
|
||||
self.roots = [FireSimServerNode() for x in range(self.no_net_num_nodes)]
|
||||
|
||||
|
|
|
@ -21,6 +21,10 @@ firesim-quadcore-nic-ddr3-llc4mb
|
|||
fireboom-singlecore-no-nic-ddr3-llc4mb
|
||||
#fireboom-singlecore-nic-lbp
|
||||
fireboom-singlecore-nic-ddr3-llc4mb
|
||||
#firesim-supernode-singlecore-nic-ddr3-llc4mb
|
||||
#firesim-supernode-quadcore-nic-ddr3-llc4mb
|
||||
#firesim-supernode-singlecore-nic-lbp
|
||||
|
||||
|
||||
[agfistoshare]
|
||||
firesim-singlecore-no-nic-lbp
|
||||
|
@ -33,6 +37,9 @@ firesim-quadcore-nic-ddr3-llc4mb
|
|||
fireboom-singlecore-no-nic-ddr3-llc4mb
|
||||
#fireboom-singlecore-nic-lbp
|
||||
fireboom-singlecore-nic-ddr3-llc4mb
|
||||
#firesim-supernode-singlecore-nic-ddr3-llc4mb
|
||||
#firesim-supernode-quadcore-nic-ddr3-llc4mb
|
||||
#firesim-supernode-singlecore-nic-lbp
|
||||
|
||||
[sharewithaccounts]
|
||||
somebodysname=123456789012
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
[firesim-singlecore-no-nic-lbp]
|
||||
DESIGN=FireSimNoNIC
|
||||
TARGET_CONFIG=FireSimRocketChipSingleCoreConfig
|
||||
PLATFORM_CONFIG=FireSimConfig
|
||||
PLATFORM_CONFIG=FireSimConfig160MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
|
@ -36,14 +36,14 @@ deploytriplet=None
|
|||
[firesim-quadcore-nic-ddr3-llc4mb]
|
||||
DESIGN=FireSim
|
||||
TARGET_CONFIG=FireSimRocketChipQuadCoreConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig90MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
[firesim-quadcore-no-nic-ddr3-llc4mb]
|
||||
DESIGN=FireSimNoNIC
|
||||
TARGET_CONFIG=FireSimRocketChipQuadCoreConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig90MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
|
@ -58,7 +58,7 @@ deploytriplet=None
|
|||
[fireboom-singlecore-no-nic-ddr3-llc4mb]
|
||||
DESIGN=FireBoomNoNIC
|
||||
TARGET_CONFIG=FireSimBoomConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig90MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
|
@ -72,6 +72,34 @@ deploytriplet=None
|
|||
[fireboom-singlecore-nic-ddr3-llc4mb]
|
||||
DESIGN=FireBoom
|
||||
TARGET_CONFIG=FireSimBoomConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig90MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
[firesim-supernode-singlecore-nic-lbp]
|
||||
DESIGN=FireSimSupernode
|
||||
TARGET_CONFIG=SupernodeFireSimRocketChipConfig
|
||||
PLATFORM_CONFIG=FireSimConfig90MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
[firesim-supernode-quadcore-nic-lbp]
|
||||
DESIGN=FireSimSupernode
|
||||
TARGET_CONFIG=SupernodeFireSimRocketChipQuadCoreConfig
|
||||
PLATFORM_CONFIG=FireSimConfig75MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
[firesim-supernode-singlecore-nic-ddr3-llc4mb]
|
||||
DESIGN=FireSimSupernode
|
||||
TARGET_CONFIG=SupernodeFireSimRocketChipConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig90MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
[firesim-supernode-quadcore-nic-ddr3-llc4mb]
|
||||
DESIGN=FireSimSupernode
|
||||
TARGET_CONFIG=SupernodeFireSimRocketChipQuadCoreConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig75MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
|
|
@ -10,27 +10,31 @@
|
|||
# own images.
|
||||
|
||||
[fireboom-singlecore-nic-ddr3-llc4mb]
|
||||
agfi=agfi-0499b46e9c4f8a451
|
||||
agfi=agfi-0fce1c408a09e4494
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[fireboom-singlecore-no-nic-ddr3-llc4mb]
|
||||
agfi=agfi-0bf2690172c6bb65a
|
||||
agfi=agfi-0f2f34654cd0ab18d
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[firesim-quadcore-nic-ddr3-llc4mb]
|
||||
agfi=agfi-068510a8f496c1e63
|
||||
agfi=agfi-061a910e29f9fcf98
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[firesim-quadcore-no-nic-ddr3-llc4mb]
|
||||
agfi=agfi-023ed229a5c85bd64
|
||||
agfi=agfi-0b2ea0c33bfcf3cea
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[firesim-singlecore-no-nic-lbp]
|
||||
agfi=agfi-0ff2fbecbc928a7e9
|
||||
agfi=agfi-04b7cc253fbf128eb
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
||||
[firesim-supernode-quadcore-nic-ddr3-llc4mb]
|
||||
agfi=agfi-012e0df3c4b90375d
|
||||
deploytripletoverride=None
|
||||
customruntimeconfig=None
|
||||
|
|
|
@ -1,27 +1,25 @@
|
|||
Debugging Using FPGA Integrated Logic Analyzers (ILA)
|
||||
=====================================================
|
||||
|
||||
Sometimes it takes too long to simulate FireSim on RTL simulators, and
|
||||
Sometimes it takes too long to simulate FireSim on RTL simulators, and
|
||||
in some occasions we would also like to debug the simulation infrastructure
|
||||
itself. For these purposes, we can use the Xilinx Integrated Logic Analyzer
|
||||
resources on the FPGA.
|
||||
resources on the FPGA.
|
||||
|
||||
ILAs allows real time sampling of pre-selected signals during FPGA runtime,
|
||||
ILAs allows real time sampling of pre-selected signals during FPGA runtime,
|
||||
and provided and interface for setting trigger and viewing samples waveforms
|
||||
from the FPGA. For more information about ILAs, please refer to the Xilinx
|
||||
guide on the topic
|
||||
|
||||
Midas provides custom Chisel annotations which allow annotating signals in the
|
||||
Chisel source code, which will automatically generate custom ILA IP for the
|
||||
fpga, and then transforme and wire the relevant signals to the ILA.
|
||||
|
||||
ILAs consume FPGA resources, and therefore it is recommended not to annotate a
|
||||
large number of signals.
|
||||
MIDAS, in its ``targetutils`` package, provides annotations for labeling
|
||||
signals directly in the Chisel source. These will be consumed by a downstream
|
||||
FIRRTL pass which wires out the annotated signals, and binds them to an
|
||||
appropriately sized ILA instance.
|
||||
|
||||
Annotating Signals
|
||||
------------------------
|
||||
|
||||
In order to annotate a signal, we must import ``midas.passes.FpgaDebugAnnotation``.
|
||||
In order to annotate a signal, we must import ``midas.targetutils.FpgaDebugAnnotation``.
|
||||
We then simply add a relevant ``FpgaDebugAnnotation(<selected_signal>)`` with the
|
||||
desired signal as an argument.
|
||||
|
||||
|
@ -29,7 +27,7 @@ Example:
|
|||
|
||||
::
|
||||
|
||||
import midas.passes.FpgaDebugAnnotation
|
||||
import midas.targetutils.FpgaDebugAnnotation
|
||||
|
||||
class SomeModuleIO(implicit p: Parameters) extends SomeIO()(p){
|
||||
val out1 = Output(Bool())
|
||||
|
@ -37,6 +35,10 @@ Example:
|
|||
chisel3.experimental.annotate(FpgaDebugAnnotation(out1))
|
||||
}
|
||||
|
||||
These annotations can be used throughout FireSim, including in MIDAS and
|
||||
Rocket-Chip Chisel sources, with the only exception being the Chisel3 sources
|
||||
themselves (eg. in Chisel3.util.Queue).
|
||||
|
||||
Note: In case the module with the annotated signal is instantiated multiple times,
|
||||
all instatiations of the annotated signal will be wired to the ILA.
|
||||
|
||||
|
|
|
@ -1,87 +1,140 @@
|
|||
Supernode
|
||||
===============
|
||||
Supernode - Multiple Simulated SoCs Per FPGA
|
||||
============================================
|
||||
|
||||
Supernode support is currently in beta. Supernode is designed to improve FPGA
|
||||
resource utilization for smaller designs and allow realistic rack topology
|
||||
simulation (32 simulated nodes) using a single ``f1.16xlarge`` instance. The
|
||||
supernode beta can be found on the ``supernode-beta`` branch of the FireSim
|
||||
repository. Supernode requires slight changes in build and runtime
|
||||
configurations. More details about supernode can be found in the `FireSim ISCA
|
||||
2018 Paper <https://sagark.org/assets/pubs/firesim-isca2018.pdf>`__.
|
||||
Supernode allows users to run multiple simulated SoCs per-FPGA in order to improve
|
||||
FPGA resource utilization and reduce cost. For example, in the case of using
|
||||
FireSim to simulate a datacenter scale system, supernode mode allows realistic
|
||||
rack topology simulation (32 simulated nodes) using a single ``f1.16xlarge``
|
||||
instance (8 FPGAs).
|
||||
|
||||
Intro
|
||||
-----------
|
||||
Below, we outline the build and runtime configuration changes needed to utilize
|
||||
supernode designs. Supernode is currently only enabled for RocketChip designs
|
||||
with NICs. More details about supernode can be found in the `FireSim ISCA 2018
|
||||
Paper <https://sagark.org/assets/pubs/firesim-isca2018.pdf>`__.
|
||||
|
||||
Supernode packs 4 identical designs into a single FPGA, and utilizes all 4 DDR
|
||||
channels available for each FPGA on AWS F1 instances. It currently does so by
|
||||
generating a wrapper top level target which encapsualtes the four simulated
|
||||
target nodes. The packed nodes are treated as 4 separate nodes, are assigned their
|
||||
own individual MAC addresses, and can perform any action a single node could:
|
||||
run different programs, interact with each other over the network, utilize
|
||||
different block device images, etc.
|
||||
Introduction
|
||||
--------------
|
||||
|
||||
Build
|
||||
-----------
|
||||
By default, supernode packs 4 identical designs into a single FPGA, and
|
||||
utilizes all 4 DDR channels available on each FPGA on AWS F1 instances. It
|
||||
currently does so by generating a wrapper top level target which encapsualtes
|
||||
the four simulated target nodes. The packed nodes are treated as 4 separate
|
||||
nodes, are assigned their own individual MAC addresses, and can perform any
|
||||
action a single node could: run different programs, interact with each other
|
||||
over the network, utilize different block device images, etc. In the networked
|
||||
case, 4 separate network links are presented to the switch-side.
|
||||
|
||||
The Supernode beta can be found on the ``supernode-beta`` branch of the FireSim
|
||||
repo. Here, we outline some of the changes between supernode and regular
|
||||
simulations. The Supernode target wrapper can be found in
|
||||
``firesim/sim/src/main/scala/SimConfigs.scala``. For example:
|
||||
Building Supernode Designs
|
||||
----------------------------
|
||||
|
||||
Here, we outline some of the changes between supernode and regular simulations
|
||||
that are required to build supernode designs.
|
||||
|
||||
The Supernode target configuration wrapper can be found in
|
||||
``firesim/sim/src/main/scala/firesim/TargetConfigs.scala``. An example wrapper
|
||||
configuration is:
|
||||
|
||||
::
|
||||
|
||||
class SupernodeFireSimRocketChipConfig extends Config(
|
||||
new WithNumNodes(4) ++
|
||||
new FireSimRocketChipConfig)
|
||||
class SupernodeFireSimRocketChipConfig extends Config(new WithNumNodes(4)
|
||||
++ new FireSimRocketChipConfig)
|
||||
|
||||
In this example, ``SupernodeFireSimRocketChipConfig`` is the wrapper, while
|
||||
``FireSimRocketChipConfig`` is the target node configuration. Therefore, if we
|
||||
want to simulate a different target configuration, we will generate a new
|
||||
Supernode wrapper, with the new target configuration. For example:
|
||||
``FireSimRocketChipConfig`` is the target node configuration. To simulate a
|
||||
different target configuration, we will generate a new supernode wrapper, with
|
||||
the new target configuration. For example, to simulate 4 quad-core nodes on one
|
||||
FPGA, you can use:
|
||||
|
||||
::
|
||||
|
||||
class SupernodeFireSimRocketChipQuadCoreConfig extends Config(
|
||||
new WithNumNodes(4) ++
|
||||
new FireSimRocketChipQuadCoreConfig)
|
||||
class SupernodeFireSimRocketChipQuadCoreConfig extends Config(new
|
||||
WithNumNodes(4) ++ new FireSimRocketChipQuadCoreConfig)
|
||||
|
||||
|
||||
Next, when defining the build recipe, we must remmber to use the supernode
|
||||
configuration: The ``DESIGN`` parameter should always be set to
|
||||
``SupernodeTop``, while the ``TARGET_CONFIG`` parameter should be set to the
|
||||
wrapper configuration that was defined in
|
||||
``firesim/sim/src/main/scala/SimConfigs.scala``. The ``PLATFORM_CONFIG`` can
|
||||
be selected the same as in regular FireSim configurations. For example:
|
||||
``FireSimSupernode``, while the ``TARGET_CONFIG`` parameter should be set to
|
||||
the wrapper configuration that was defined in
|
||||
``firesim/sim/src/main/scala/firesim/TargetConfigs.scala``. The
|
||||
``PLATFORM_CONFIG`` can be selected the same as in regular FireSim
|
||||
configurations. For example:
|
||||
|
||||
::
|
||||
|
||||
DESIGN=SupernodeTop
|
||||
DESIGN=FireSimSupernode
|
||||
TARGET_CONFIG=SupernodeFireSimRocketChipQuadCoreConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig
|
||||
PLATFORM_CONFIG=FireSimDDR3FRFCFSLLC4MBConfig90MHz
|
||||
instancetype=c4.4xlarge
|
||||
deploytriplet=None
|
||||
|
||||
|
||||
We currently do not provide pre-built AGFIs for supernode. You must build your
|
||||
own, using the supplied samples on the ``supernode-beta`` branch.
|
||||
We currently provide a single pre-built AGFI for supernode of 4 quad-core
|
||||
RocketChips with DDR3 memory models. You can build your own AGFI, using the supplied samples in
|
||||
``config_build_recipes.ini``. Importantly, in order to meet FPGA timing
|
||||
contraints, Supernode target may require lower host clock frequencies.
|
||||
host clock frequencies can be configured as parts of the PLATFORM_CONFIG in
|
||||
``config_build_recipes.ini``.
|
||||
|
||||
Running simulations
|
||||
--------------------
|
||||
Running Supernode Simulations
|
||||
-----------------------------
|
||||
|
||||
Running FireSim in supernode mode follows the same process as in
|
||||
"regular" mode. Currently, the only difference is that the standard input and
|
||||
standard output of the simulated nodes are written to files in the dispatched
|
||||
simulation directory, rather than the main simulation screen.
|
||||
"regular" mode. Currently, the only difference is that the main simulation
|
||||
screen remains with the name ``fsim0``, while the three other simulation screens
|
||||
can be accessed by attaching ``screen`` to ``uartpty1``, ``uartpty2``, ``uartpty3``
|
||||
respectively. All simulation screens will generate uart logs (``uartlog1``,
|
||||
``uartlog2``, ``uartlog3``). Notice that you must use ``sudo`` in order to
|
||||
attach to the uartpty or view the uart logs. The additional uart logs will not
|
||||
be copied back to the manager instance by default (as in a "regular" FireSim
|
||||
simulation). It is neccessary to specify the copying of the additional uartlogs
|
||||
(uartlog1, uartlog2, uartlog3) in the workload definition.
|
||||
|
||||
Here are some important pieces that you can use to run an example 32-node config
|
||||
on a single ``f1.16xlarge``. Better documentation will be available later:
|
||||
Supernode topologies utilize a ``FireSimSuperNodeServerNode`` class in order to
|
||||
represent one of the 4 simulated target nodes which also represents a single
|
||||
FPGA mapping, while using a ``FireSimDummyServerNode`` class which represent
|
||||
the other three simulated target nodes which do not represent an FPGA mapping.
|
||||
In supernode mode, topologies should always add nodes in pairs of 4, as one
|
||||
``FireSimSuperNodeServerNode`` and three ``FireSimDummyServerNode`` s.
|
||||
|
||||
- Sample runtime config: https://github.com/firesim/firesim/blob/supernode-beta/deploy/sample-backup-configs/sample_config_runtime.ini
|
||||
- Sample topology definition: https://github.com/firesim/firesim/blob/supernode-beta/deploy/runtools/user_topology.py#L33
|
||||
Various example Supernode topologies are provided, ranging from 4 simulated
|
||||
target nodes to 1024 simulated target nodes.
|
||||
|
||||
Below are a couple of useful examples as templates for writing custom
|
||||
Supernode topologies.
|
||||
|
||||
|
||||
A sample Supernode topology of 4 simulated target nodes which can fit on a
|
||||
single ``f1.2xlarge`` is:
|
||||
|
||||
::
|
||||
|
||||
def supernode_example_4config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
servers = [FireSimSuperNodeServerNode()] + [FireSimDummyServerNode() for x in range(3)]
|
||||
self.roots[0].add_downlinks(servers)
|
||||
|
||||
|
||||
A sample Supernode topology of 32 simulated target nodes which can fit on a
|
||||
single ``f1.16xlarge`` is:
|
||||
|
||||
::
|
||||
|
||||
def supernode_example_32config(self):
|
||||
self.roots = [FireSimSwitchNode()]
|
||||
servers = UserTopologies.supernode_flatten([[FireSimSuperNodeServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode(), FireSimDummyServerNode()] for y in range(8)])
|
||||
self.roots[0].add_downlinks(servers)
|
||||
|
||||
|
||||
Supernode ``config_runtime.ini`` requires selecting a supernode agfi in conjunction with a defined supernode topology.
|
||||
|
||||
|
||||
Work in Progress!
|
||||
--------------------
|
||||
|
||||
We are currently working on restructuring supernode support to support a
|
||||
wider-variety of use cases. More documentation will follow once we complete
|
||||
this rewrite.
|
||||
We are currently working on restructuring supernode to support a
|
||||
wider-variety of use cases (including non-networked cases, and increased
|
||||
packing of nodes). More documentation will follow.
|
||||
Not all FireSim features are currently available on Supernode. As a
|
||||
rule-of-thumb, target-related features have a higher likelihood of being
|
||||
supported "out-of-the-box", while features which involve external interfaces
|
||||
(such as TracerV) has a lesser likelihood of being supported "out-of-the-box"
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit bca30e63c91b30e6db9b253077da805ca69513e7
|
||||
Subproject commit ef82afc73bf863e148bf46b817cb90fd433e4c1d
|
28
sim/Makefile
28
sim/Makefile
|
@ -20,20 +20,24 @@ default: compile
|
|||
SBT ?= sbt
|
||||
SBT_FLAGS ?= -J-Xmx16G -J-Xss8M -J-XX:MaxPermSize=256M -J-XX:MaxMetaspaceSize=512M -J-XX:ReservedCodeCacheSize=1G ++2.12.4
|
||||
|
||||
sbt:
|
||||
$(SBT) $(SBT_FLAGS) shell
|
||||
test:
|
||||
$(SBT) $(SBT_FLAGS) test
|
||||
|
||||
########################
|
||||
# Timestamp & Patching #
|
||||
########################
|
||||
firesim_base_dir := $(abspath .)
|
||||
timestamps = $(addprefix $(firesim_base_dir)/, $(addsuffix .timestamp, firrtl))
|
||||
|
||||
$(firesim_base_dir)/firrtl.timestamp: $(shell find $(firesim_base_dir)/firrtl/$(src_path) -name "*.scala")
|
||||
cd $(firesim_base_dir)/firrtl && $(SBT) $(SBT_FLAGS) publishLocal
|
||||
touch $@
|
||||
# Manage the FIRRTL dependency manually
|
||||
FIRRTL_JAR ?= $(firesim_base_dir)/lib/firrtl.jar
|
||||
FIRRTL_SUBMODULE_DIR ?= $(firesim_base_dir)/firrtl
|
||||
$(FIRRTL_JAR): $(shell find $(FIRRTL_SUBMODULE_DIR)/src/main/scala -iname "*.scala")
|
||||
$(MAKE) -C $(FIRRTL_SUBMODULE_DIR) SBT="$(SBT) $(SBT_FLAGS)" root_dir=$(FIRRTL_SUBMODULE_DIR) build-scala
|
||||
mkdir -p $(@D)
|
||||
cp -p $(FIRRTL_SUBMODULE_DIR)/utils/bin/firrtl.jar $(FIRRTL_JAR)
|
||||
|
||||
firrtl: $(FIRRTL_JAR)
|
||||
.PHONY: firrtl
|
||||
|
||||
# Phony targets for launching the sbt shell and running scalatests
|
||||
sbt: $(FIRRTL_JAR)
|
||||
$(SBT) $(SBT_FLAGS) shell
|
||||
test: $(FIRRTL_JAR)
|
||||
$(SBT) $(SBT_FLAGS) test
|
||||
|
||||
PLATFORM := f1
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ build_dir := $(fpga_work_dir)/build
|
|||
verif_dir := $(fpga_work_dir)/verif
|
||||
fpga_v := $(fpga_work_dir)/design/cl_firesim_generated.sv
|
||||
ila_work_dir := $(fpga_work_dir)/design/ila_files/
|
||||
fpga_vh := $(fpga_work_dir)/design/cl_firesim_generated_defines.vh
|
||||
|
||||
$(fpga_work_dir)/stamp: $(shell find $(board_dir)/cl_firesim -name '*')
|
||||
mkdir -p $(@D)
|
||||
|
@ -120,6 +121,9 @@ $(fpga_v): $(VERILOG) $(fpga_work_dir)/stamp
|
|||
sed -i "s/\$$random/64'b0/g" $@
|
||||
sed -i 's/fatal/fatal(0, "")/g' $@
|
||||
|
||||
$(fpga_vh): $(VERILOG) $(fpga_work_dir)/stamp
|
||||
cp -f $(GENERATED_DIR)/$(@F) $@
|
||||
|
||||
.PHONY: $(ila_work_dir)
|
||||
$(ila_work_dir): $(verilog) $(fpga_work_dir)/stamp
|
||||
cp -f $(GENERATED_DIR)/firesim_ila_insert_* $(fpga_work_dir)/design/ila_files/
|
||||
|
@ -128,7 +132,8 @@ $(ila_work_dir): $(verilog) $(fpga_work_dir)/stamp
|
|||
|
||||
# Goes as far as setting up the build directory without running the cad job
|
||||
# Used by the manager before passing a build to a remote machine
|
||||
replace-rtl: $(fpga_v) $(ila_work_dir)
|
||||
replace-rtl: $(fpga_v) $(ila_work_dir) $(fpga_vh)
|
||||
|
||||
.PHONY: replace-rtl
|
||||
|
||||
$(firesim_base_dir)/scripts/checkpoints/$(target_sim_tuple): $(fpga_work_dir)/stamp
|
||||
|
|
|
@ -7,13 +7,9 @@ lazy val commonSettings = Seq(
|
|||
traceLevel := 15,
|
||||
scalacOptions ++= Seq("-deprecation","-unchecked","-Xsource:2.11"),
|
||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.1" % "test",
|
||||
libraryDependencies += "org.json4s" %% "json4s-native" % "3.5.3",
|
||||
libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.5.3",
|
||||
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full),
|
||||
resolvers ++= Seq(
|
||||
Resolver.sonatypeRepo("snapshots"),
|
||||
Resolver.sonatypeRepo("releases"),
|
||||
Resolver.mavenLocal)
|
||||
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
|
||||
)
|
||||
|
||||
// Fork each scala test for now, to work around persistent mutable state
|
||||
|
@ -25,14 +21,62 @@ def isolateAllTests(tests: Seq[TestDefinition]) = tests map { test =>
|
|||
|
||||
testGrouping in Test := isolateAllTests( (definedTests in Test).value )
|
||||
|
||||
lazy val rocketchip = RootProject(file("target-rtl/firechip/rocket-chip"))
|
||||
lazy val boom = project in file("target-rtl/firechip/boom") settings commonSettings dependsOn rocketchip
|
||||
lazy val sifiveip = project in file("target-rtl/firechip/sifive-blocks") settings commonSettings dependsOn rocketchip
|
||||
lazy val testchipip = project in file("target-rtl/firechip/testchipip") settings commonSettings dependsOn rocketchip
|
||||
lazy val icenet = project in file("target-rtl/firechip/icenet") settings commonSettings dependsOn (rocketchip, testchipip)
|
||||
val rocketChipDir = file("target-rtl/firechip/rocket-chip")
|
||||
val fireChipDir = file("target-rtl/firechip")
|
||||
|
||||
// Subproject definitions begin
|
||||
// NB: FIRRTL dependency is unmanaged (and dropped in sim/lib)
|
||||
lazy val chisel = (project in rocketChipDir / "chisel3")
|
||||
|
||||
// Contains annotations & firrtl passes you may wish to use in rocket-chip without
|
||||
// introducing a circular dependency between RC and MIDAS
|
||||
lazy val midasTargetUtils = (project in file("midas/targetutils"))
|
||||
.settings(commonSettings)
|
||||
.dependsOn(chisel)
|
||||
|
||||
// Rocket-chip dependencies (subsumes making RC a RootProject)
|
||||
lazy val hardfloat = (project in rocketChipDir / "hardfloat")
|
||||
.settings(
|
||||
commonSettings,
|
||||
crossScalaVersions := Seq("2.11.12", "2.12.4"))
|
||||
.dependsOn(chisel, midasTargetUtils)
|
||||
lazy val macros = (project in rocketChipDir / "macros")
|
||||
.settings(commonSettings)
|
||||
|
||||
// HACK: I'm strugging to override settings in rocket-chip's build.sbt (i want
|
||||
// the subproject to register a new library dependendency on midas's targetutils library)
|
||||
// So instead, avoid the existing build.sbt altogether and specify the project's root at src/
|
||||
lazy val rocketchip = (project in rocketChipDir / "src")
|
||||
.settings(
|
||||
commonSettings,
|
||||
scalaSource in Compile := baseDirectory.value / "main" / "scala",
|
||||
resourceDirectory in Compile := baseDirectory.value / "main" / "resources")
|
||||
.dependsOn(chisel, hardfloat, macros, midasTargetUtils)
|
||||
|
||||
// Target-specific dependencies
|
||||
lazy val boom = (project in fireChipDir / "boom")
|
||||
.settings(commonSettings)
|
||||
.dependsOn(rocketchip)
|
||||
lazy val sifiveip = (project in fireChipDir / "sifive-blocks")
|
||||
.settings(commonSettings)
|
||||
.dependsOn(rocketchip)
|
||||
lazy val testchipip = (project in fireChipDir / "testchipip")
|
||||
.settings(commonSettings)
|
||||
.dependsOn(rocketchip)
|
||||
lazy val icenet = (project in fireChipDir / "icenet")
|
||||
.settings(commonSettings)
|
||||
.dependsOn(rocketchip, testchipip)
|
||||
|
||||
// MIDAS-specific dependencies
|
||||
lazy val mdf = RootProject(file("barstools/mdf/scalalib"))
|
||||
lazy val barstools = project in file("barstools/macros") settings commonSettings dependsOn (mdf, rocketchip)
|
||||
lazy val midas = project in file("midas") settings commonSettings dependsOn barstools
|
||||
lazy val barstools = (project in file("barstools/macros"))
|
||||
.settings(commonSettings)
|
||||
.dependsOn(mdf, rocketchip)
|
||||
lazy val midas = (project in file("midas"))
|
||||
.settings(commonSettings)
|
||||
.dependsOn(barstools)
|
||||
|
||||
lazy val firesim = project in file(".") settings commonSettings dependsOn (midas, sifiveip, testchipip, icenet, boom)
|
||||
// Finally the root project
|
||||
lazy val firesim = (project in file("."))
|
||||
.settings(commonSettings)
|
||||
.dependsOn(rocketchip, midas, boom, icenet, sifiveip)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit eb84570a52705d75ec7e4e632fa3961716ffb360
|
||||
Subproject commit f938398a2ab6231ab8a2e6b83cd788b0c0c8e5cb
|
|
@ -9,21 +9,63 @@
|
|||
#define DEFAULT_STEPSIZE (2004765L)
|
||||
#endif
|
||||
|
||||
serial_t::serial_t(simif_t* sim, const std::vector<std::string>& args, SERIALWIDGET_struct * mmio_addrs):
|
||||
endpoint_t(sim), sim(sim), fesvr(args) {
|
||||
serial_t::serial_t(simif_t* sim, const std::vector<std::string>& args, SERIALWIDGET_struct * mmio_addrs, int serialno, uint64_t mem_host_offset):
|
||||
endpoint_t(sim), sim(sim), mem_host_offset(mem_host_offset) {
|
||||
|
||||
this->mmio_addrs = mmio_addrs;
|
||||
|
||||
std::string num_equals = std::to_string(serialno) + std::string("=");
|
||||
std::string prog_arg = std::string("+prog") + num_equals;
|
||||
std::vector<std::string> args_vec;
|
||||
char** argv_arr;
|
||||
int argc_count = 0;
|
||||
|
||||
step_size = DEFAULT_STEPSIZE;
|
||||
for (auto &arg: args) {
|
||||
if (arg.find("+fesvr-step-size=") == 0) {
|
||||
step_size = atoi(arg.c_str()+17);
|
||||
}
|
||||
if (arg.find(prog_arg) == 0)
|
||||
{
|
||||
std::string clean_target_args = const_cast<char*>(arg.c_str()) + prog_arg.length();
|
||||
|
||||
std::istringstream ss(clean_target_args);
|
||||
std::string token;
|
||||
while(std::getline(ss, token, ' ')) {
|
||||
args_vec.push_back(token);
|
||||
argc_count = argc_count + 1;
|
||||
}
|
||||
}
|
||||
else if (arg.find(std::string("+prog")) == 0)
|
||||
{
|
||||
//Eliminate arguments for other fesvrs
|
||||
}
|
||||
else
|
||||
{
|
||||
args_vec.push_back(arg);
|
||||
argc_count = argc_count + 1;
|
||||
}
|
||||
}
|
||||
|
||||
argv_arr = new char*[args_vec.size()];
|
||||
for(size_t i = 0; i < args_vec.size(); ++i)
|
||||
{
|
||||
(argv_arr)[i] = new char[(args_vec)[i].size() + 1];
|
||||
std::strcpy((argv_arr)[i], (args_vec)[i].c_str());
|
||||
}
|
||||
|
||||
//debug for command line arguments
|
||||
printf("command line for program %d. argc=%d:\n", serialno, argc_count);
|
||||
for(int i = 0; i < argc_count; i++) { printf("%s ", (argv_arr)[i]); }
|
||||
printf("\n");
|
||||
|
||||
std::vector<std::string> args_new(argv_arr, argv_arr + argc_count);
|
||||
fesvr = new firesim_fesvr_t(args_new);
|
||||
}
|
||||
|
||||
serial_t::~serial_t() {
|
||||
free(this->mmio_addrs);
|
||||
free(fesvr);
|
||||
}
|
||||
|
||||
void serial_t::init() {
|
||||
|
@ -36,15 +78,15 @@ void serial_t::go() {
|
|||
}
|
||||
|
||||
void serial_t::send() {
|
||||
while(fesvr.data_available() && read(this->mmio_addrs->in_ready)) {
|
||||
write(this->mmio_addrs->in_bits, fesvr.recv_word());
|
||||
while(fesvr->data_available() && read(this->mmio_addrs->in_ready)) {
|
||||
write(this->mmio_addrs->in_bits, fesvr->recv_word());
|
||||
write(this->mmio_addrs->in_valid, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void serial_t::recv() {
|
||||
while(read(this->mmio_addrs->out_valid)) {
|
||||
fesvr.send_word(read(this->mmio_addrs->out_bits));
|
||||
fesvr->send_word(read(this->mmio_addrs->out_bits));
|
||||
write(this->mmio_addrs->out_ready, 1);
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +97,7 @@ void serial_t::handle_loadmem_read(fesvr_loadmem_t loadmem) {
|
|||
mpz_t buf;
|
||||
mpz_init(buf);
|
||||
while (loadmem.size > 0) {
|
||||
sim->read_mem(loadmem.addr, buf);
|
||||
sim->read_mem(loadmem.addr + mem_host_offset, buf);
|
||||
|
||||
// If the read word is 0; mpz_export seems to return an array with length 0
|
||||
size_t beats_requested = (loadmem.size/sizeof(uint32_t) > MEM_DATA_CHUNK) ?
|
||||
|
@ -66,35 +108,35 @@ void serial_t::handle_loadmem_read(fesvr_loadmem_t loadmem) {
|
|||
uint32_t* data = (uint32_t*)mpz_export(NULL, &non_zero_beats, -1, sizeof(uint32_t), 0, 0, buf);
|
||||
for (size_t j = 0; j < beats_requested; j++) {
|
||||
if (j < non_zero_beats) {
|
||||
fesvr.send_word(data[j]);
|
||||
fesvr->send_word(data[j]);
|
||||
} else {
|
||||
fesvr.send_word(0);
|
||||
fesvr->send_word(0);
|
||||
}
|
||||
}
|
||||
loadmem.size -= beats_requested * sizeof(uint32_t);
|
||||
}
|
||||
mpz_clear(buf);
|
||||
// Switch back to fesvr for it to process read data
|
||||
fesvr.tick();
|
||||
fesvr->tick();
|
||||
}
|
||||
|
||||
void serial_t::handle_loadmem_write(fesvr_loadmem_t loadmem) {
|
||||
assert(loadmem.size <= 1024);
|
||||
static char buf[1024];
|
||||
fesvr.recv_loadmem_data(buf, loadmem.size);
|
||||
fesvr->recv_loadmem_data(buf, loadmem.size);
|
||||
mpz_t data;
|
||||
mpz_init(data);
|
||||
mpz_import(data, (loadmem.size + sizeof(uint32_t) - 1)/sizeof(uint32_t), -1, sizeof(uint32_t), 0, 0, buf); \
|
||||
sim->write_mem_chunk(loadmem.addr, data, loadmem.size);
|
||||
sim->write_mem_chunk(loadmem.addr + mem_host_offset, data, loadmem.size);
|
||||
mpz_clear(data);
|
||||
}
|
||||
|
||||
void serial_t::serial_bypass_via_loadmem() {
|
||||
fesvr_loadmem_t loadmem;
|
||||
while (fesvr.has_loadmem_reqs()) {
|
||||
while (fesvr->has_loadmem_reqs()) {
|
||||
// Check for reads first as they preceed a narrow write;
|
||||
if (fesvr.recv_loadmem_read_req(loadmem)) handle_loadmem_read(loadmem);
|
||||
if (fesvr.recv_loadmem_write_req(loadmem)) handle_loadmem_write(loadmem);
|
||||
if (fesvr->recv_loadmem_read_req(loadmem)) handle_loadmem_read(loadmem);
|
||||
if (fesvr->recv_loadmem_write_req(loadmem)) handle_loadmem_write(loadmem);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,10 +146,10 @@ void serial_t::tick() {
|
|||
// Collect all the responses from the target
|
||||
this->recv();
|
||||
// Punt to FESVR
|
||||
if (!fesvr.data_available()) {
|
||||
fesvr.tick();
|
||||
if (!fesvr->data_available()) {
|
||||
fesvr->tick();
|
||||
}
|
||||
if (fesvr.has_loadmem_reqs()) {
|
||||
if (fesvr->has_loadmem_reqs()) {
|
||||
serial_bypass_via_loadmem();
|
||||
}
|
||||
if (!terminate()) {
|
||||
|
|
|
@ -24,17 +24,19 @@ struct serial_data_t {
|
|||
class serial_t: public endpoint_t
|
||||
{
|
||||
public:
|
||||
serial_t(simif_t* sim, const std::vector<std::string>& args, SERIALWIDGET_struct * mmio_addrs);
|
||||
serial_t(simif_t* sim, const std::vector<std::string>& args, SERIALWIDGET_struct * mmio_addrs, int serialno, uint64_t mem_host_offset);
|
||||
~serial_t();
|
||||
virtual void init();
|
||||
virtual void tick();
|
||||
virtual bool terminate(){ return fesvr.done(); }
|
||||
virtual int exit_code(){ return fesvr.exit_code(); }
|
||||
virtual bool terminate(){ return fesvr->done(); }
|
||||
virtual int exit_code(){ return fesvr->exit_code(); }
|
||||
|
||||
private:
|
||||
SERIALWIDGET_struct * mmio_addrs;
|
||||
simif_t* sim;
|
||||
firesim_fesvr_t fesvr;
|
||||
firesim_fesvr_t* fesvr;
|
||||
// host memory offset based on the number of memory models and their size
|
||||
uint64_t mem_host_offset;
|
||||
// Number of target cycles between fesvr interactions
|
||||
uint32_t step_size;
|
||||
// Tell the widget to start enqueuing tokens
|
||||
|
|
|
@ -204,31 +204,12 @@ void simplenic_t::init() {
|
|||
|
||||
//#define TOKENVERIFY
|
||||
|
||||
// checking for token loss
|
||||
uint32_t next_token_from_fpga = 0x0;
|
||||
uint32_t next_token_from_socket = 0x0;
|
||||
|
||||
uint64_t iter = 0;
|
||||
|
||||
int currentround = 0;
|
||||
int nextround = 1;
|
||||
|
||||
#ifdef TOKENVERIFY
|
||||
uint64_t timeelapsed_cycles = 0;
|
||||
#endif
|
||||
|
||||
void simplenic_t::tick() {
|
||||
struct timespec tstart, tend;
|
||||
|
||||
uint32_t token_bytes_obtained_from_fpga = 0;
|
||||
uint32_t token_bytes_sent_to_fpga = 0;
|
||||
|
||||
//#define DEBUG_NIC_PRINT
|
||||
|
||||
while (true) { // break when we don't have 5k tokens
|
||||
token_bytes_obtained_from_fpga = 0;
|
||||
token_bytes_sent_to_fpga = 0;
|
||||
|
||||
uint32_t tokens_this_round = 0;
|
||||
|
||||
uint32_t output_tokens_available = read(mmio_addrs->outgoing_count);
|
||||
|
@ -252,6 +233,7 @@ void simplenic_t::tick() {
|
|||
iter++;
|
||||
niclog_printf("read fpga iter %ld\n", iter);
|
||||
#endif
|
||||
uint32_t token_bytes_obtained_from_fpga = 0;
|
||||
token_bytes_obtained_from_fpga = pull(
|
||||
dma_addr,
|
||||
pcis_read_bufs[currentround],
|
||||
|
@ -327,6 +309,7 @@ void simplenic_t::tick() {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
uint32_t token_bytes_sent_to_fpga = 0;
|
||||
token_bytes_sent_to_fpga = push(
|
||||
dma_addr,
|
||||
pcis_write_bufs[currentround],
|
||||
|
@ -339,8 +322,6 @@ void simplenic_t::tick() {
|
|||
}
|
||||
|
||||
currentround = (currentround + 1) % 2;
|
||||
nextround = (nextround + 1) % 2;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ class simplenic_t: public endpoint_t
|
|||
{
|
||||
public:
|
||||
simplenic_t(simif_t* sim, std::vector<std::string> &args,
|
||||
SIMPLENICWIDGET_struct *addrs, int simplenicno,
|
||||
long dma_addr);
|
||||
SIMPLENICWIDGET_struct *addrs, int simplenicno,
|
||||
long dma_addr);
|
||||
~simplenic_t();
|
||||
|
||||
virtual void init();
|
||||
|
@ -37,7 +37,19 @@ class simplenic_t: public endpoint_t
|
|||
FILE * niclog;
|
||||
SIMPLENICWIDGET_struct *mmio_addrs;
|
||||
bool loopback;
|
||||
long dma_addr;
|
||||
|
||||
// checking for token loss
|
||||
uint32_t next_token_from_fpga = 0x0;
|
||||
uint32_t next_token_from_socket = 0x0;
|
||||
|
||||
uint64_t iter = 0;
|
||||
|
||||
int currentround = 0;
|
||||
|
||||
// only for TOKENVERIFY
|
||||
uint64_t timeelapsed_cycles = 0;
|
||||
|
||||
long dma_addr;
|
||||
};
|
||||
#endif // SIMPLENICWIDGET_struct_guard
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
*
|
||||
* Reset to zero once consumed.
|
||||
*/
|
||||
|
||||
// This is fine for multiple UARTs because UARTs > uart 0 will use pty, not stdio
|
||||
char specialchar = 0;
|
||||
|
||||
void sighand(int s) {
|
||||
|
|
|
@ -50,16 +50,13 @@ firesim_top_t::firesim_top_t(int argc, char** argv)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
// TODO: Serial multiple copy support
|
||||
#ifdef SERIALWIDGET_struct_guard
|
||||
SERIALWIDGET_0_substruct_create;
|
||||
add_endpoint(new serial_t(this, args, SERIALWIDGET_0_substruct));
|
||||
#endif
|
||||
|
||||
#ifdef NASTIWIDGET_0
|
||||
endpoints.push_back(new sim_mem_t(this, argc, argv));
|
||||
#endif
|
||||
|
||||
std::vector<uint64_t> host_mem_offsets;
|
||||
uint64_t host_mem_offset = -0x80000000LL;
|
||||
#ifdef MEMMODEL_0
|
||||
fpga_models.push_back(new FpgaMemoryModel(
|
||||
this,
|
||||
|
@ -70,7 +67,73 @@ firesim_top_t::firesim_top_t(int argc, char** argv)
|
|||
MEMMODEL_0_W_num_registers,
|
||||
(const unsigned int*) MEMMODEL_0_W_addrs,
|
||||
(const char* const*) MEMMODEL_0_W_names),
|
||||
argc, argv, "memory_stats.csv", 1L << TARGET_MEM_ADDR_BITS));
|
||||
argc, argv, "memory_stats.csv", 1L << TARGET_MEM_ADDR_BITS , host_mem_offset));
|
||||
host_mem_offsets.push_back(host_mem_offset);
|
||||
host_mem_offset += (1ULL << MEMMODEL_0_target_addr_bits);
|
||||
#endif
|
||||
|
||||
#ifdef MEMMODEL_1
|
||||
fpga_models.push_back(new FpgaMemoryModel(
|
||||
this,
|
||||
// Casts are required for now since the emitted type can change...
|
||||
AddressMap(MEMMODEL_1_R_num_registers,
|
||||
(const unsigned int*) MEMMODEL_1_R_addrs,
|
||||
(const char* const*) MEMMODEL_1_R_names,
|
||||
MEMMODEL_1_W_num_registers,
|
||||
(const unsigned int*) MEMMODEL_1_W_addrs,
|
||||
(const char* const*) MEMMODEL_1_W_names),
|
||||
argc, argv, "memory_stats.csv", 1L << TARGET_MEM_ADDR_BITS, host_mem_offset));
|
||||
host_mem_offsets.push_back(host_mem_offset);
|
||||
host_mem_offset += 1ULL << MEMMODEL_1_target_addr_bits;
|
||||
#endif
|
||||
|
||||
#ifdef MEMMODEL_2
|
||||
fpga_models.push_back(new FpgaMemoryModel(
|
||||
this,
|
||||
// Casts are required for now since the emitted type can change...
|
||||
AddressMap(MEMMODEL_2_R_num_registers,
|
||||
(const unsigned int*) MEMMODEL_2_R_addrs,
|
||||
(const char* const*) MEMMODEL_2_R_names,
|
||||
MEMMODEL_2_W_num_registers,
|
||||
(const unsigned int*) MEMMODEL_2_W_addrs,
|
||||
(const char* const*) MEMMODEL_2_W_names),
|
||||
argc, argv, "memory_stats.csv", 1L << TARGET_MEM_ADDR_BITS, host_mem_offset));
|
||||
host_mem_offsets.push_back(host_mem_offset);
|
||||
host_mem_offset += 1ULL << MEMMODEL_2_target_addr_bits;
|
||||
#endif
|
||||
|
||||
#ifdef MEMMODEL_3
|
||||
fpga_models.push_back(new FpgaMemoryModel(
|
||||
this,
|
||||
// Casts are required for now since the emitted type can change...
|
||||
AddressMap(MEMMODEL_3_R_num_registers,
|
||||
(const unsigned int*) MEMMODEL_3_R_addrs,
|
||||
(const char* const*) MEMMODEL_3_R_names,
|
||||
MEMMODEL_3_W_num_registers,
|
||||
(const unsigned int*) MEMMODEL_3_W_addrs,
|
||||
(const char* const*) MEMMODEL_3_W_names),
|
||||
argc, argv, "memory_stats.csv", 1L << TARGET_MEM_ADDR_BITS, host_mem_offset));
|
||||
host_mem_offsets.push_back(host_mem_offset);
|
||||
host_mem_offset += 1ULL << MEMMODEL_3_target_addr_bits;
|
||||
#endif
|
||||
|
||||
#ifdef SERIALWIDGET_struct_guard
|
||||
#ifdef SERIALWIDGET_0_PRESENT
|
||||
SERIALWIDGET_0_substruct_create;
|
||||
add_endpoint(new serial_t(this, args, SERIALWIDGET_0_substruct, 0, host_mem_offsets[0]));
|
||||
#endif
|
||||
#ifdef SERIALWIDGET_1_PRESENT
|
||||
SERIALWIDGET_1_substruct_create;
|
||||
add_endpoint(new serial_t(this, args, SERIALWIDGET_1_substruct, 1, host_mem_offsets[1]));
|
||||
#endif
|
||||
#ifdef SERIALWIDGET_2_PRESENT
|
||||
SERIALWIDGET_2_substruct_create;
|
||||
add_endpoint(new serial_t(this, args, SERIALWIDGET_2_substruct, 2, host_mem_offsets[2]));
|
||||
#endif
|
||||
#ifdef SERIALWIDGET_3_PRESENT
|
||||
SERIALWIDGET_3_substruct_create;
|
||||
add_endpoint(new serial_t(this, args, SERIALWIDGET_3_substruct, 3, host_mem_offsets[3]));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BLOCKDEVWIDGET_struct_guard
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
#endif
|
||||
|
||||
#ifdef MEMMODEL_0
|
||||
uint64_t host_mem_offset = 0x00000000LL;
|
||||
fpga_models.push_back(new FpgaMemoryModel(
|
||||
this,
|
||||
// Casts are required for now since the emitted type can change...
|
||||
|
@ -38,7 +39,7 @@ public:
|
|||
MEMMODEL_0_W_num_registers,
|
||||
(const unsigned int*) MEMMODEL_0_W_addrs,
|
||||
(const char* const*) MEMMODEL_0_W_names),
|
||||
argc, argv, "memory_stats.csv", 1L << TARGET_MEM_ADDR_BITS));
|
||||
argc, argv, "memory_stats.csv", 1L << TARGET_MEM_ADDR_BITS, host_mem_offset));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ chisel_srcs = $(foreach submodule,$(submodules),$(shell find $(base_dir)/$(submo
|
|||
|
||||
common_chisel_args = $(patsubst $(base_dir)/%,%,$(GENERATED_DIR)) $(DESIGN_PACKAGE) $(DESIGN) $(TARGET_CONFIG_PACKAGE) $(TARGET_CONFIG) $(PLATFORM_CONFIG_PACKAGE) $(PLATFORM_CONFIG)
|
||||
|
||||
$(VERILOG) $(HEADER): $(chisel_srcs) $(timestamps)
|
||||
$(VERILOG) $(HEADER): $(chisel_srcs) $(FIRRTL_JAR)
|
||||
mkdir -p $(@D)
|
||||
$(SBT) $(SBT_FLAGS) \
|
||||
"runMain $(DESIGN_PACKAGE).FireSimGenerator $(if $(STROBER),strober,midas) $(common_chisel_args)"
|
||||
|
|
|
@ -22,7 +22,7 @@ chisel_srcs = $(foreach submodule,$(submodules),$(shell find $(base_dir)/$(submo
|
|||
|
||||
common_chisel_args = $(patsubst $(base_dir)/%,%,$(GENERATED_DIR)) $(PROJECT) $(DESIGN) $(TARGET_PROJECT) $(TARGET_CONFIG) $(PLATFORM_PROJECT) $(PLATFORM_CONFIG)
|
||||
|
||||
$(VERILOG) $(HEADER): $(chisel_srcs) $(timestamps)
|
||||
$(VERILOG) $(HEADER): $(chisel_srcs) $(FIRRTL_JAR)
|
||||
cd $(base_dir) && $(SBT) $(SBT_FLAGS) \
|
||||
"runMain $(PROJECT).Generator midas $(DESIGN) $(patsubst $(base_dir)/%,%,$(dir $@)) $(PLATFORM) $(macro_lib)"
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ trait HasFireSimGeneratorUtilities extends HasGeneratorUtilities with HasTestSui
|
|||
case "FireBoom" => LazyModule(new FireBoom()(params)).module
|
||||
case "FireSimNoNIC" => LazyModule(new FireSimNoNIC()(params)).module
|
||||
case "FireBoomNoNIC" => LazyModule(new FireBoomNoNIC()(params)).module
|
||||
case "FireSimSupernode" => new FireSimSupernode()(params)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,6 +123,17 @@ trait HasFireSimGeneratorUtilities extends HasGeneratorUtilities with HasTestSui
|
|||
fw.close
|
||||
f
|
||||
}
|
||||
|
||||
// Capture FPGA-toolflow related verilog defines
|
||||
def generateHostVerilogHeader() {
|
||||
val headerName = "cl_firesim_generated_defines.vh"
|
||||
val requestedFrequency = hostParams(DesiredHostFrequency)
|
||||
val availableFrequenciesMhz = Seq(190, 175, 160, 90, 85, 75)
|
||||
if (!availableFrequenciesMhz.contains(requestedFrequency)) {
|
||||
throw new RuntimeException(s"Requested frequency (${requestedFrequency} MHz) is not available.\nAllowed options: ${availableFrequenciesMhz} MHz")
|
||||
}
|
||||
writeOutputFile(headerName, s"`define SELECTED_FIRESIM_CLOCK ${requestedFrequency}\n")
|
||||
}
|
||||
}
|
||||
|
||||
trait HasTestSuites {
|
||||
|
@ -206,6 +218,7 @@ object FireSimGenerator extends App with HasFireSimGeneratorUtilities {
|
|||
|
||||
elaborateAndCompileWithMidas
|
||||
generateTestSuiteMakefrags
|
||||
generateHostVerilogHeader
|
||||
}
|
||||
|
||||
// A runtime-configuration generation for memory models
|
||||
|
|
|
@ -14,6 +14,11 @@ import firesim.endpoints._
|
|||
object BaseParamsKey extends Field[BaseParams]
|
||||
object LlcKey extends Field[Option[LLCParams]]
|
||||
object DramOrganizationKey extends Field[DramOrganizationParams]
|
||||
object DesiredHostFrequency extends Field[Int](190) // In MHz
|
||||
|
||||
class WithDesiredHostFrequency(freq: Int) extends Config((site, here, up) => {
|
||||
case DesiredHostFrequency => freq
|
||||
})
|
||||
|
||||
// Removes default endpoints from the MIDAS-provided config
|
||||
class BasePlatformConfig extends Config(new Config((site, here, up) => {
|
||||
|
@ -170,6 +175,7 @@ class FRFCFS16GBQuadRankLLC4MB3Div extends Config(
|
|||
* determine which driver to build.
|
||||
*******************************************************************************/
|
||||
class FireSimConfig extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new WithSerialWidget ++
|
||||
new WithUARTWidget ++
|
||||
new WithSimpleNICWidget ++
|
||||
|
@ -178,7 +184,20 @@ class FireSimConfig extends Config(
|
|||
new WithTracerVWidget ++
|
||||
new BasePlatformConfig)
|
||||
|
||||
class FireSimConfig160MHz extends Config(
|
||||
new WithDesiredHostFrequency(160) ++
|
||||
new FireSimConfig)
|
||||
|
||||
class FireSimConfig90MHz extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new FireSimConfig)
|
||||
|
||||
class FireSimConfig75MHz extends Config(
|
||||
new WithDesiredHostFrequency(75) ++
|
||||
new FireSimConfig)
|
||||
|
||||
class FireSimClockDivConfig extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new WithSerialWidget ++
|
||||
new WithUARTWidget ++
|
||||
new WithSimpleNICWidget ++
|
||||
|
@ -187,6 +206,7 @@ class FireSimClockDivConfig extends Config(
|
|||
new BasePlatformConfig)
|
||||
|
||||
class FireSimDDR3Config extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new WithSerialWidget ++
|
||||
new WithUARTWidget ++
|
||||
new WithSimpleNICWidget ++
|
||||
|
@ -195,6 +215,7 @@ class FireSimDDR3Config extends Config(
|
|||
new BasePlatformConfig)
|
||||
|
||||
class FireSimDDR3LLC4MBConfig extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new WithSerialWidget ++
|
||||
new WithUARTWidget ++
|
||||
new WithSimpleNICWidget ++
|
||||
|
@ -203,6 +224,7 @@ class FireSimDDR3LLC4MBConfig extends Config(
|
|||
new BasePlatformConfig)
|
||||
|
||||
class FireSimDDR3FRFCFSConfig extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new WithSerialWidget ++
|
||||
new WithUARTWidget ++
|
||||
new WithSimpleNICWidget ++
|
||||
|
@ -211,6 +233,7 @@ class FireSimDDR3FRFCFSConfig extends Config(
|
|||
new BasePlatformConfig)
|
||||
|
||||
class FireSimDDR3FRFCFSLLC4MBConfig extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new WithSerialWidget ++
|
||||
new WithUARTWidget ++
|
||||
new WithSimpleNICWidget ++
|
||||
|
@ -218,7 +241,20 @@ class FireSimDDR3FRFCFSLLC4MBConfig extends Config(
|
|||
new FRFCFS16GBQuadRankLLC4MB ++
|
||||
new BasePlatformConfig)
|
||||
|
||||
class FireSimDDR3FRFCFSLLC4MBConfig160MHz extends Config(
|
||||
new WithDesiredHostFrequency(160) ++
|
||||
new FireSimDDR3FRFCFSLLC4MBConfig)
|
||||
|
||||
class FireSimDDR3FRFCFSLLC4MBConfig90MHz extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new FireSimDDR3FRFCFSLLC4MBConfig)
|
||||
|
||||
class FireSimDDR3FRFCFSLLC4MBConfig75MHz extends Config(
|
||||
new WithDesiredHostFrequency(75) ++
|
||||
new FireSimDDR3FRFCFSLLC4MBConfig)
|
||||
|
||||
class FireSimDDR3FRFCFSLLC4MB3ClockDivConfig extends Config(
|
||||
new WithDesiredHostFrequency(90) ++
|
||||
new WithSerialWidget ++
|
||||
new WithUARTWidget ++
|
||||
new WithSimpleNICWidget ++
|
||||
|
|
|
@ -162,3 +162,42 @@ class FireSimBoomDualCoreConfig extends Config(
|
|||
|
||||
class FireSimBoomTracedConfig extends Config(
|
||||
new WithTraceBoom ++ new FireSimBoomConfig)
|
||||
|
||||
|
||||
//**********************************************************************************
|
||||
//* Supernode Configurations
|
||||
//*********************************************************************************/
|
||||
class WithNumNodes(n: Int) extends Config((pname, site, here) => {
|
||||
case NumNodes => n
|
||||
})
|
||||
|
||||
class SupernodeFireSimRocketChipConfig extends Config(
|
||||
new WithNumNodes(4) ++
|
||||
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||
new FireSimRocketChipConfig)
|
||||
|
||||
class SupernodeFireSimRocketChipSingleCoreConfig extends Config(
|
||||
new WithNumNodes(4) ++
|
||||
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||
new FireSimRocketChipSingleCoreConfig)
|
||||
|
||||
class SupernodeFireSimRocketChipDualCoreConfig extends Config(
|
||||
new WithNumNodes(4) ++
|
||||
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||
new FireSimRocketChipDualCoreConfig)
|
||||
|
||||
class SupernodeFireSimRocketChipQuadCoreConfig extends Config(
|
||||
new WithNumNodes(4) ++
|
||||
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||
new FireSimRocketChipQuadCoreConfig)
|
||||
|
||||
class SupernodeFireSimRocketChipHexaCoreConfig extends Config(
|
||||
new WithNumNodes(4) ++
|
||||
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||
new FireSimRocketChipHexaCoreConfig)
|
||||
|
||||
class SupernodeFireSimRocketChipOctaCoreConfig extends Config(
|
||||
new WithNumNodes(4) ++
|
||||
new WithExtMemSize(0x200000000L) ++ // 8GB
|
||||
new FireSimRocketChipOctaCoreConfig)
|
||||
|
||||
|
|
|
@ -7,9 +7,14 @@ import freechips.rocketchip.diplomacy.LazyModule
|
|||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.util.HeterogeneousBag
|
||||
import freechips.rocketchip.amba.axi4.AXI4Bundle
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.diplomacy.LazyModule
|
||||
import boom.system.{BoomSubsystem, BoomSubsystemModule}
|
||||
import icenet._
|
||||
import testchipip._
|
||||
import testchipip.SerialAdapter.SERIAL_IF_WIDTH
|
||||
import sifive.blocks.devices.uart._
|
||||
import java.io.File
|
||||
|
||||
|
@ -167,3 +172,48 @@ class FireBoomNoNICModuleImp[+L <: FireBoomNoNIC](l: L) extends BoomSubsystemMod
|
|||
|
||||
class FireBoomNoNICModuleImpTraced[+L <: FireBoomNoNIC](l: L) extends FireBoomNoNICModuleImp(l)
|
||||
with CanHaveBoomTraceIO
|
||||
|
||||
case object NumNodes extends Field[Int]
|
||||
|
||||
class SupernodeIO(
|
||||
nNodes: Int,
|
||||
serialWidth: Int,
|
||||
bagPrototype: HeterogeneousBag[AXI4Bundle])(implicit p: Parameters)
|
||||
extends Bundle {
|
||||
|
||||
val serial = Vec(nNodes, new SerialIO(serialWidth))
|
||||
val mem_axi = Vec(nNodes, bagPrototype.cloneType)
|
||||
val bdev = Vec(nNodes, new BlockDeviceIO)
|
||||
val net = Vec(nNodes, new NICIOvonly)
|
||||
val uart = Vec(nNodes, new UARTPortIO)
|
||||
|
||||
override def cloneType = new SupernodeIO(nNodes, serialWidth, bagPrototype).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
|
||||
class FireSimSupernode(implicit p: Parameters) extends Module {
|
||||
val nNodes = p(NumNodes)
|
||||
val nodes = Seq.fill(nNodes) {
|
||||
Module(LazyModule(new FireSim).module)
|
||||
}
|
||||
|
||||
val io = IO(new SupernodeIO(nNodes, SERIAL_IF_WIDTH, nodes(0).mem_axi4))
|
||||
|
||||
io.mem_axi.zip(nodes.map(_.mem_axi4)).foreach {
|
||||
case (out, mem_axi4) => out <> mem_axi4
|
||||
}
|
||||
io.serial <> nodes.map(_.serial)
|
||||
io.bdev <> nodes.map(_.bdev)
|
||||
io.net <> nodes.map(_.net)
|
||||
io.uart <> nodes.map(_.uart(0))
|
||||
nodes.foreach{ case n => {
|
||||
n.debug.clockeddmi.get.dmi.req.valid := false.B
|
||||
n.debug.clockeddmi.get.dmi.resp.ready := false.B
|
||||
n.debug.clockeddmi.get.dmiClock := clock
|
||||
n.debug.clockeddmi.get.dmiReset := reset.toBool
|
||||
n.debug.clockeddmi.get.dmi.req.bits.data := DontCare
|
||||
n.debug.clockeddmi.get.dmi.req.bits.addr := DontCare
|
||||
n.debug.clockeddmi.get.dmi.req.bits.op := DontCare
|
||||
} }
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
package firesim.passes
|
||||
|
||||
import midas.passes.FirrtlFpgaDebugAnnotation
|
||||
import midas.targetutils.FirrtlFpgaDebugAnnotation
|
||||
|
||||
import firrtl._
|
||||
import firrtl.ir._
|
||||
|
|
Loading…
Reference in New Issue