Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
829bcb5
misc: SRNoC model
kunpai Mar 24, 2025
a04257d
misc: Add comments and license
kunpai Mar 25, 2025
636407d
misc: Add test script to configs
kunpai Mar 25, 2025
4ed063c
misc: Encoding for zero in SRNoC
kunpai Mar 29, 2025
f60b438
misc: Add more traffic patterns
kunpai Mar 29, 2025
57ba6d8
misc: Update SRNoC model
kunpai Mar 31, 2025
1c11035
misc: Update SRNoC stats
kunpai Apr 1, 2025
de5cf23
misc: Fix exitSimLoop bug
kunpai Apr 1, 2025
ce40530
misc: Effect of Frequency on SRNoC
kunpai Apr 1, 2025
539ce83
misc: Refactor out precomputed schedule
kunpai Apr 1, 2025
f2b8a57
misc: SuperNetwork functionality moved to Layer
kunpai Apr 2, 2025
56b6802
misc: Minor style changes
kunpai Apr 2, 2025
77e24cc
misc: Miscellaneous changes to SRNoC Model
kunpai Apr 2, 2025
aba23df
misc: Infinite packets implemented
kunpai Apr 4, 2025
921375c
misc: Fix bug related to multiple layers
kunpai Apr 4, 2025
24a4090
misc: Move delay parameters into Layer
kunpai Apr 4, 2025
895e2ac
misc: Implement ability to choose traffic mode
kunpai Apr 5, 2025
6e4ae6d
misc: Implement file-based schedule & other misc changes
kunpai Apr 5, 2025
da8c574
misc: Fix argument parsers in SRNoC config script
kunpai Apr 5, 2025
50c2070
misc: Code clean-up
kunpai Apr 5, 2025
46c60aa
misc: Add hold time
kunpai Apr 7, 2025
35fa81a
misc: Improve timing model
kunpai Apr 13, 2025
29eb7fe
misc: Add All-to-All traffic mode
kunpai Apr 13, 2025
a7c882c
misc: Add tornado traffic pattern
kunpai Apr 13, 2025
4488ca9
misc: Dynamic histogram bins
kunpai Apr 14, 2025
6532ca2
misc: Change timing delays and add new stat
kunpai Apr 16, 2025
c6cf554
misc: Small change in SConscript
kunpai Apr 16, 2025
6563633
misc: Move data generation to scheduler
kunpai Apr 16, 2025
e562b2d
misc: Add shuffling to all-to-all traffic
kunpai Apr 16, 2025
1bd8267
misc: Update SRNoC params
kunpai Apr 16, 2025
0495bcc
misc: Refactor out # of RL Time Slots as configurable
kunpai Apr 17, 2025
b86fc78
misc: Rename DataCell to BufferedPort
kunpai Apr 17, 2025
9af8d57
misc: Add some fatals
kunpai Apr 17, 2025
5fdfc19
misc: Payload specific delay formula changed
kunpai Apr 18, 2025
81c46e6
misc: Add bit complement and nearest neighbor traffic patterns
kunpai Apr 18, 2025
e6488b3
misc: Multiple packets from 1 src to 1 dest in 1 window
kunpai Apr 21, 2025
39da8b7
misc: Align area and power model with ground truth
kunpai Apr 21, 2025
a383268
misc: Minor changes
kunpai May 1, 2025
2c16f0b
misc: Replace packet with value
kunpai May 1, 2025
ec287d3
misc: Replace packet with value in config script
kunpai May 1, 2025
398bd50
misc: Add latency tracking, no buffer mode
kunpai May 17, 2025
7a9cdcf
misc: Add param to target messages per second, bug fixes
kunpai May 21, 2025
a387d9c
misc: Add buffer depth
kunpai May 22, 2025
d98525b
misc: Configurable buffer depth
kunpai May 22, 2025
6572cb5
misc: Merge SRNoC and refactor buffer depth
kunpai May 22, 2025
1bba2bb
misc: Fixing bugs
kunpai May 28, 2025
20247bb
misc: Add active sources
kunpai Jun 7, 2025
0f60637
misc: Move seq/rand active ports bool
kunpai Jun 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
364 changes: 364 additions & 0 deletions configs/supernetwork/SRNoC.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,364 @@
# Copyright (c) 2025 The Regents of the University of California
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import argparse
from enum import Enum as PyEnum

import m5
from m5.objects import *
from m5.params import *


class NetworkDelays(PyEnum):
CROSSPOINT_DELAY = 4.1 # picoseconds
MERGER_DELAY = 8.84
SPLITTER_DELAY = 2.06
CIRCUIT_VARIABILITY = 1.2
VARIABILITY_COUNTING_NETWORK = 4.38
CROSSPOINT_SETUP_TIME = 8.0
CROSSPOINT_HOLD_TIME = 8.0


class ComponentPower(PyEnum):
# Static power consumption in microwatts
SPLITTER_STATIC = 5.98
MERGER_STATIC = 5.0
CROSSPOINT_STATIC = 7.9
COUNTING_NETWORK_STATIC = 66.82
TFF_STATIC = 10.8

# Active power consumption in nanowatts
SPLITTER_ACTIVE = 83.2
MERGER_ACTIVE = 69.6
CROSSPOINT_ACTIVE = 60.7
COUNTING_NETWORK_ACTIVE = 163.0
TFF_ACTIVE = 105.6


class ComponentJJ(PyEnum):
# Number of Josephson Junctions (JJs)
SPLITTER = 3
MERGER = 5
CROSSPOINT = 13
COUNTING_NETWORK = 60
TFF = 10


def calculate_power_and_area(radix):
# Scale counting network power based on network radix
counting_network_ratio = (radix / 2) // 4.0
print(f"Counting network ratio: {counting_network_ratio}")
counting_network_active_power = (
ComponentPower.COUNTING_NETWORK_ACTIVE.value * counting_network_ratio
)
counting_network_static_power = (
ComponentPower.COUNTING_NETWORK_STATIC.value * counting_network_ratio
)
counting_network_jj = int(
ComponentJJ.COUNTING_NETWORK.value * counting_network_ratio
)

# Calculate number of components based on network radix
r = radix // 2
num_counting_networks = r
num_crosspoints = r * r
num_splitters = r * (r - 1)
num_mergers = r * (r - 1)

# Calculate active power consumption
active_power = (
num_counting_networks * counting_network_active_power
+ num_crosspoints * ComponentPower.CROSSPOINT_ACTIVE.value
+ num_splitters * ComponentPower.SPLITTER_ACTIVE.value
+ num_mergers * ComponentPower.MERGER_ACTIVE.value
)

# Calculate static power consumption
static_power = (
num_counting_networks * counting_network_static_power
+ num_crosspoints * ComponentPower.CROSSPOINT_STATIC.value
+ num_splitters * ComponentPower.SPLITTER_STATIC.value
+ num_mergers * ComponentPower.MERGER_STATIC.value
)

# Convert power units
active_power *= 1e-9 # nanowatts to watts
static_power *= 1e-6 # microwatts to watts
total_power = active_power + static_power

# Calculate total Josephson Junctions
total_jj = (
num_counting_networks * counting_network_jj
+ num_crosspoints * ComponentJJ.CROSSPOINT.value
+ num_splitters * ComponentJJ.SPLITTER.value
+ num_mergers * ComponentJJ.MERGER.value
)

# Log and store power and area statistics
print(f"Active power: {active_power:.6f} W")
print(f"Static power: {static_power:.6f} W")
print(f"Total power: {total_power:.6f} W")
print(f"Total JJ: {total_jj}")

return {
"active_power": active_power,
"static_power": static_power,
"total_power": total_power,
"total_jj": total_jj,
}


def create_shared_parser():
"""
Parser for arguments shared across all traffic modes.
"""
shared_parser = argparse.ArgumentParser(add_help=False)
shared_parser.add_argument(
"--frequencies-per-layer",
type=str,
nargs="+",
required=True,
help="Number of time slots per connection window",
)
return shared_parser


def create_base_parser():
parser = argparse.ArgumentParser(description="SuperNetwork Simulation")
parser.add_argument(
"--num-ports", type=int, default=10, help="Number of BufferedPorts"
)
parser.add_argument(
"--maximum-values", type=int, default=0, help="Maximum values"
)
parser.add_argument(
"--buffer-depth",
type=int,
default=1,
help="Buffer depth (number of values in the buffer)",
)
parser.add_argument(
"--values-per-port-per-window",
type=int,
default=1,
help="values per port per window",
)

# add mutually exclusive group for active source selection
active_src_group = parser.add_mutually_exclusive_group()
active_src_group.add_argument(
"--active-src-count",
type=int,
default=-1,
help="Number of active sources in the network (-1 for all)",
)
active_src_group.add_argument(
"--active-src-fraction",
type=float,
default=1.0,
help="Fraction of active sources in the network (default is 1 for all)",
)
parser.add_argument(
"--active-src-sequence",
action="store_true",
help="If true, active sources are selected in a sequence; otherwise, randomly",
)
return parser


def parse_arguments():
shared_parser = create_shared_parser()
base_parser = create_base_parser()
subparsers = base_parser.add_subparsers(dest="traffic_mode", required=True)

# random traffic
random_parser = subparsers.add_parser(
"random", parents=[shared_parser], help="Random traffic mode"
)

bit_complement_parser = subparsers.add_parser(
"bit-complement",
parents=[shared_parser],
help="Bit-complement traffic mode",
)

nearest_neighbor_parser = subparsers.add_parser(
"nearest-neighbor",
parents=[shared_parser],
help="Nearest-neighbor traffic mode",
)
nearest_neighbor_parser.add_argument(
"--shuffle",
action="store_true",
help="Shuffle the destinations for nearest-neighbor mode",
)

# all-to-all traffic
all_to_all_parser = subparsers.add_parser(
"all-to-all", parents=[shared_parser], help="All-to-all traffic mode"
)
all_to_all_parser.add_argument(
"--shuffle",
action="store_true",
help="Shuffle the destinations for all-to-all mode",
)

tornado_parser = subparsers.add_parser(
"tornado", parents=[shared_parser], help="Tornado traffic mode"
)

# hotspot traffic
hotspot_parser = subparsers.add_parser(
"hotspot", parents=[shared_parser], help="Hotspot traffic mode"
)
hotspot_parser.add_argument(
"--hotspot-addr", type=int, required=True, help="Hotspot address"
)
hotspot_parser.add_argument(
"--hotspot-fraction",
type=float,
required=True,
help="Fraction of hotspot traffic",
)

# file traffic
file_parser = subparsers.add_parser(
"file", parents=[shared_parser], help="File-based traffic mode"
)
file_parser.add_argument(
"--file-path", type=str, required=True, help="Path to the traffic file"
)

return base_parser.parse_args()


def main():
args = parse_arguments()

# Create the root SimObject and system.
root = Root(full_system=False)
root.system = System()

# Set up the clock and voltage domains.
root.system.clk_domain = SrcClockDomain()
root.system.clk_domain.clock = "1.4GHz"
root.system.clk_domain.voltage_domain = VoltageDomain()

# Create the BufferedPorts.
num_ports = args.num_ports
buffered_ports = [BufferedPort() for _ in range(num_ports)]

if args.traffic_mode != "file":
schedule_path = "" # Force schedule_path to be empty if not using file-based traffic mode.
else:
schedule_path = args.file_path

# Create Layers
layers = [
Layer(
buffered_ports=buffered_ports,
max_values=args.maximum_values,
schedule_path=schedule_path,
crosspoint_delay=NetworkDelays.CROSSPOINT_DELAY.value,
merger_delay=NetworkDelays.MERGER_DELAY.value,
splitter_delay=NetworkDelays.SPLITTER_DELAY.value,
circuit_variability=NetworkDelays.CIRCUIT_VARIABILITY.value,
variability_counting_network=NetworkDelays.VARIABILITY_COUNTING_NETWORK.value,
crosspoint_setup_time=NetworkDelays.CROSSPOINT_SETUP_TIME.value,
hold_time=NetworkDelays.CROSSPOINT_HOLD_TIME.value,
values_per_port_per_window=args.values_per_port_per_window,
buffer_depth=args.buffer_depth,
clk_domain=SrcClockDomain(
clock=frequency,
voltage_domain=VoltageDomain(),
),
active_src_count=args.active_src_count,
active_src_frac=args.active_src_fraction,
active_src_seq=args.active_src_sequence,
)
for frequency in args.frequencies_per_layer
]

# Create the SuperNetwork and add the layers.
super_network = SuperNetwork()
super_network.layers = layers
root.system.super_network = super_network

# Print test configuration.
print("SRNoC Test Configuration")
print("==============================")
print(f"Number of BufferedPort: {num_ports}")
print(f"Frequencies per Layer: {args.frequencies_per_layer}")
print()
print("Power and Area Statistics")
print("==============================")
power_and_area = calculate_power_and_area(radix=(num_ports * 2))
print()

if args.maximum_values:
print(f"Maximum values: {args.maximum_values}")
if getattr(args, "file_path", None):
print(f"File Path: {args.file_path}")
print()

# Instantiate the simulation.
m5.instantiate()

# Set the traffic mode based on the chosen sub-command.
if args.traffic_mode == "hotspot":
for layer in layers:
layer.setHotspotTrafficMode(
args.hotspot_addr, args.hotspot_fraction
)
elif args.traffic_mode == "all-to-all":
for layer in layers:
if args.shuffle:
layer.setShuffle()
layer.setAllToAllTrafficMode()
elif args.traffic_mode == "random":
for layer in layers:
layer.setRandomTrafficMode()
elif args.traffic_mode == "tornado":
for layer in layers:
layer.setTornadoTrafficMode()
elif args.traffic_mode == "bit-complement":
for layer in layers:
layer.setBitComplementTrafficMode()
elif args.traffic_mode == "nearest-neighbor":
for layer in layers:
if args.shuffle:
layer.setShuffle()
layer.setNearestNeighborTrafficMode()
else: # file mode selected.
for layer in layers:
layer.setRandomTrafficMode()

exit_event = m5.simulate()
print(f"Exiting @ tick {m5.curTick()} because {exit_event.getCause()}")


if __name__ == "__m5_main__":
main()
Loading