Skip to content

Commit 6f74fb7

Browse files
Merge pull request #3757 from AlexandreSinger/feature-clk-switch-network
[Clocks] Added Clock Switch Grid Syntax
2 parents 7243411 + 6db59c4 commit 6f74fb7

40 files changed

Lines changed: 10248 additions & 604 deletions

doc/src/arch/reference.rst

Lines changed: 124 additions & 18 deletions
Large diffs are not rendered by default.

libs/libarchfpga/src/clock_types.h

Lines changed: 145 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,174 @@
11
#pragma once
22

33
#include <string>
4+
#include <vector>
45

6+
#include "switchblock_types.h"
7+
8+
/// @brief The topology of a dedicated clock network, as declared by a <clock_network>'s type attribute.
59
enum class e_clock_type {
6-
SPINE,
7-
RIB,
8-
H_TREE
10+
SPINE, ///< A single horizontal wire, tapped by vertical spines (see e_clock_type::RIB below).
11+
RIB, ///< A single vertical wire, tapped from/tapping into horizontal spines.
12+
H_TREE, ///< Not yet implemented.
13+
SWITCH_GRID ///< A grid of clock switch boxes; see t_clock_switch_grid_arch.
914
};
1015

16+
/// @brief Metal layer electrical properties for a clock network's wires.
1117
struct t_metal_layer {
12-
float r_metal;
13-
float c_metal;
18+
float r_metal; ///< Resistance per unit length.
19+
float c_metal; ///< Capacitance per unit length.
1420
};
1521

22+
/// @brief How a rib/spine's wire repeats (tiles) across the device.
1623
struct t_wire_repeat {
17-
std::string x;
18-
std::string y;
24+
std::string x; ///< Repeat pitch in the x direction.
25+
std::string y; ///< Repeat pitch in the y direction.
26+
27+
/// @brief Upper bound for how far this network repeats, in whichever axis is its own
28+
/// tiling direction (x for a spine's column-tiling repeatx, y for a rib's row-tiling
29+
/// repeaty). Defaults to the full device width/height, preserving the "tile all the way
30+
/// to the device edge" behavior; a smaller bound lets a rib/spine repeat within only part
31+
/// of the device (e.g. one clock quadrant) instead of needing a network that spans the
32+
/// whole device and is shared/cheated across quadrants.
33+
std::string end_x = "W";
34+
std::string end_y = "H";
1935
};
2036

37+
/// @brief The extent of a single rib/spine wire segment.
2138
struct t_wire {
22-
std::string start;
23-
std::string end;
24-
std::string position;
39+
std::string start; ///< Start coordinate along the wire's own axis.
40+
std::string end; ///< End coordinate along the wire's own axis.
41+
std::string position; ///< Coordinate along the wire's perpendicular axis.
2542
};
2643

44+
/// @brief Where and how a rib/spine is driven from another clock network.
2745
struct t_clock_drive {
28-
std::string name;
29-
std::string offset;
30-
int arch_switch_idx;
46+
std::string name; ///< Name of the switch point other networks connect to when driving this one.
47+
std::string offset; ///< Coordinate, along the wire's own axis, of the drive point.
48+
int arch_switch_idx; ///< Index into the architecture's switch list of the driving switch.
3149
};
3250

51+
/// @brief Where and how often a rib/spine exposes tap points to other clock networks.
3352
struct t_clock_taps {
34-
std::string name;
35-
std::string offset;
36-
std::string increment;
53+
std::string name; ///< Name of the switch point other networks tap into.
54+
std::string offset; ///< Coordinate, along the wire's own axis, of the first tap.
55+
std::string increment; ///< Spacing between repeated taps; empty/absent means a single tap.
56+
};
57+
58+
/// @brief Whether a <switch_point> in a <clock_switch_grid> is a drive or a tap point.
59+
enum class e_clock_switch_grid_point_type {
60+
DRIVE,
61+
TAP
62+
};
63+
64+
/// @brief A single <switch_point> entry within a <clock_switch_grid>. Unlike the rib/spine
65+
/// drive/tap, offsets are 2D (a switch box location on the grid) and multiple drive and/or
66+
/// tap points are allowed.
67+
struct t_clock_switch_grid_point {
68+
std::string name; ///< Name other clock connections reference this point by.
69+
e_clock_switch_grid_point_type type; ///< DRIVE or TAP.
70+
std::string xoffset; ///< Switch box column this point sits at.
71+
std::string yoffset; ///< Switch box row this point sits at.
72+
73+
/// @brief Repeat this tap point across the grid every xincr/yincr switch boxes (like the
74+
/// rib/spine tap xincr/yincr), instead of at just one location. "0" (the default) means no
75+
/// repeat, i.e. a single point. Only meaningful for TAP points; DRIVE points are always a
76+
/// single location.
77+
std::string xincr = "0";
78+
std::string yincr = "0";
79+
80+
int arch_switch_idx = -1; ///< Index into the architecture's switch list; only set for DRIVE points.
81+
};
82+
83+
/// @brief One <switch_pattern> under a custom clock_switch_grid: which built-in switch-block
84+
/// permutation type applies, and where. Formula strings are resolved later (setup_clocks.cpp)
85+
/// against the same W/H vars as the rest of this grid. This is the same deferred-formula convention as
86+
/// startx/repeatx/chan_w below, so this still works with "auto" device layouts (general
87+
/// routing's own <switchblock_location> XY_SPECIFIED explicitly rejects "auto" layouts; clock
88+
/// networks don't need that restriction). Fully independent of general routing's
89+
/// <switchblocklist>/<switch_block type="custom">: different XML location, different struct,
90+
/// no shared namespace.
91+
struct t_clock_switch_pattern {
92+
std::string name; ///< Name for error messages; not otherwise referenced.
93+
e_switch_block_type switch_block_type; ///< WILTON/SUBSET/UNIVERSAL/FULL/CUSTOM.
94+
e_sb_location location = e_sb_location::E_EVERYWHERE; ///< Which switch boxes this pattern applies to.
95+
96+
// Only meaningful when location == E_XY_SPECIFIED.
97+
std::string x, y; ///< Exact location; empty means "use the region below".
98+
std::string startx = "0", endx = "W-1", repeatx = "0", incrx = "1"; ///< X region, when location == E_XY_SPECIFIED and x/y are empty.
99+
std::string starty = "0", endy = "H-1", repeaty = "0", incry = "1"; ///< Y region, when location == E_XY_SPECIFIED and x/y are empty.
100+
101+
/// @brief Turn permutation formulas parsed from this pattern's <switchfuncs> child, reusing
102+
/// general routing's own <switchblock> grammar/types verbatim (see parse_switchblocks.h's
103+
/// read_sb_switchfuncs/t_permutation_map). Formulas stay as strings here; t/W are only
104+
/// known per-track at RR-graph build time, same as general routing. Only meaningful when
105+
/// switch_block_type == CUSTOM.
106+
t_permutation_map permutation_map;
107+
};
108+
109+
/// @brief Architecture description of a grid of clock switch boxes: at every
110+
/// (repeatx, repeaty)-spaced location, clock wires connect to their adjacent switch boxes'
111+
/// wires according to switch_block_type (or switch_patterns, if CUSTOM).
112+
struct t_clock_switch_grid_arch {
113+
std::string metal_layer; ///< Name of the metal layer this grid's wires are drawn on.
114+
std::string startx; ///< X coordinate of the grid's first switch box.
115+
std::string starty; ///< Y coordinate of the grid's first switch box.
116+
std::string repeatx; ///< Switch box column pitch.
117+
std::string repeaty; ///< Switch box row pitch.
118+
std::string chan_w; ///< Number of tracks per inter-switch-box wire segment.
119+
std::string switch_name; ///< Name of the switch used for wire-to-wire connections within a switch box.
120+
int arch_switch_idx = -1; ///< Index into the architecture's switch list, resolved from switch_name.
121+
122+
/// @brief How the wires incident to each switch box connect to one another. Defaults to
123+
/// FULL (every incident wire mutually reachable), matching the original minimal
124+
/// implementation. CUSTOM picks a per-location built-in type from switch_patterns below
125+
/// instead of a single type for the whole grid.
126+
e_switch_block_type switch_block_type = e_switch_block_type::FULL;
127+
128+
/// @brief Only populated when switch_block_type == CUSTOM. Matched in list order; first
129+
/// match wins.
130+
std::vector<t_clock_switch_pattern> switch_patterns;
131+
132+
/// @brief Wire length, in switch-box hops (not tiles), i.e. how many repeatx/repeaty
133+
/// pitches a hop wire spans before terminating at a switch box. Defaults to "1", matching
134+
/// the original one-hop-per-switch-box implementation. Expressed in hop units (rather than
135+
/// tiles) so it stays independent of repeatx/repeaty: changing the switch-box pitch doesn't
136+
/// require also rescaling length to keep the same topology.
137+
std::string length = "1";
138+
139+
/// @brief Whether the grid's hop wires are BI_DIRECTIONAL (one node per track, entered and
140+
/// exited from either end) or UNI_DIRECTIONAL (each track flows one way, like general
141+
/// routing's unidirectional segments). Unidirectional requires an even chan_w (half the
142+
/// tracks INC, half DEC). Required in the arch XML, matching how <segment type=.../> works
143+
/// in general routing.
144+
e_directionality directionality = BI_DIRECTIONAL;
145+
146+
std::vector<t_clock_switch_grid_point> switch_points; ///< This grid's <switch_point> drive/tap entries.
37147
};
38148

149+
/// @brief Architecture description of one <clock_network>, as parsed from the arch XML.
39150
struct t_clock_network_arch {
40-
std::string name;
41-
int num_inst;
151+
std::string name; ///< Unique name, referenced by <clock_routing> connections.
152+
int num_inst; ///< Number of instances of this network to create (e.g. one per clock quadrant).
153+
154+
e_clock_type type; ///< SPINE, RIB, H_TREE, or SWITCH_GRID; determines which of the fields below apply.
42155

43-
e_clock_type type;
156+
std::string metal_layer; ///< Name of the metal layer this network's wire is drawn on. Unused when type == SWITCH_GRID.
157+
t_wire wire; ///< Wire extent. Unused when type == SWITCH_GRID.
158+
t_wire_repeat repeat; ///< Repeat/tiling parameters. Unused when type == SWITCH_GRID.
159+
t_clock_drive drive; ///< Drive point. Unused when type == SWITCH_GRID.
160+
t_clock_taps tap; ///< Tap point(s). Unused when type == SWITCH_GRID.
44161

45-
std::string metal_layer;
46-
t_wire wire;
47-
t_wire_repeat repeat;
48-
t_clock_drive drive;
49-
t_clock_taps tap;
162+
t_clock_switch_grid_arch switch_grid; ///< Switch grid parameters; only used when type == SWITCH_GRID.
50163
};
51164

165+
/// @brief Architecture description of one <clock_routing> connection, wiring a clock network's
166+
/// tap/drive point either to/from general-purpose routing or to/from another clock network.
52167
struct t_clock_connection_arch {
53-
std::string from;
54-
std::string to;
55-
int arch_switch_idx;
56-
std::string locationx;
57-
std::string locationy;
58-
float fc;
168+
std::string from; ///< Source: a clock network's switch point name, or a routing/tile pin reference.
169+
std::string to; ///< Destination: a clock network's switch point name, or a routing/tile pin reference.
170+
int arch_switch_idx; ///< Index into the architecture's switch list of the connecting switch.
171+
std::string locationx; ///< X coordinate this connection is made at.
172+
std::string locationy; ///< Y coordinate this connection is made at.
173+
float fc; ///< Fraction of source tracks/pins each destination connects to.
59174
};

0 commit comments

Comments
 (0)