Merge remote-tracking branch 'origin/dev' into gapbs

This commit is contained in:
Sarah Zhou 2018-11-30 23:20:56 +00:00
commit 911577c674
29 changed files with 847 additions and 175 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()) {

View File

@ -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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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
}

View File

@ -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)"

View File

@ -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)"

View File

@ -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

View File

@ -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 ++

View File

@ -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)

View File

@ -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
} }
}

View File

@ -2,7 +2,7 @@
package firesim.passes
import midas.passes.FirrtlFpgaDebugAnnotation
import midas.targetutils.FirrtlFpgaDebugAnnotation
import firrtl._
import firrtl.ir._