From 1cb95b979c4ddd2603a09ba8326af47a1a0eead2 Mon Sep 17 00:00:00 2001 From: zakn-amd <133808894+zakn-amd@users.noreply.github.com> Date: Mon, 30 Oct 2023 20:40:42 -0700 Subject: [PATCH 1/2] PIP Clarifications (#33) * Update scoring page to mention interconnect tiles Signed-off-by: Zak Nafziger * reword for clarity Co-authored-by: eddieh-xlnx * move comment about pips only to details page Signed-off-by: Zak Nafziger * less technical language in initial explanation Co-authored-by: eddieh-xlnx * update Router section of details Signed-off-by: Zak Nafziger * improve specificity in details Co-authored-by: eddieh-xlnx * Mention INT prefix ahead of table * further wording changes Co-authored-by: eddieh-xlnx --------- Signed-off-by: Zak Nafziger Co-authored-by: eddieh-xlnx --- docs/details.md | 7 ++++--- docs/score.md | 14 +++++++++----- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/docs/details.md b/docs/details.md index 7d16591..a7e98a7 100644 --- a/docs/details.md +++ b/docs/details.md @@ -5,7 +5,7 @@ * The target device for this contest will be the AMD/Xilinx UltraScale+ xcvu3p. * Competing routers must consume a pre-placed and partially-routed [FPGA Interchange Format](http://www.rapidwright.io/docs/FPGA_Interchange_Format.html) Physical Netlist - and emit a fully routed Physical Netlist. + and emit a fully routed Physical Netlist formed by enabling some number of routing switches (termed PIPs). * The exact scoring criteria is presented on the [Scoring Criteria](score.html) webpage. In general, contestant routers are expected, in order of importance, to: 1. Produce a legal routing solution ... @@ -41,8 +41,9 @@ Should contestants wish to test/train with more benchmarks than those that are p #### Router With just the pre-placed but partially-routed input Physical Netlist, competitors are required to route all -signal nets while preserving all existing placement and routing. This fully-routed result must then be written -out as a new Physical Netlist. +signal nets while preserving all existing placement and routing. In practice this +is achieved by only inserting FPGAIF routeSegment objects of the type `pip` into the +netlist. This fully-routed result must then be written out as a new Physical Netlist. #### Post-routing Once this fully-routed Physical Netlist is ready, RapidWright takes it again and combines it with the previous diff --git a/docs/score.md b/docs/score.md index 19ef96f..80fd24d 100644 --- a/docs/score.md +++ b/docs/score.md @@ -53,10 +53,13 @@ between a BEL output pin and a BEL input pin is simply the sum of the wirelength of every routeSegment that must be traced through to reach the input from the output. For the purposes of the contest, only routeSegments of the type `pip` can -affect the wirelength, since these are the only type of routeSegment that can -be added by contest routers. All other types of routeSegment (`belPin`, -`sitePin`, `sitePIP`) are therefore assumed to have a wirelength of zero. -Thus for a portion of a path that looks like this: +affect the wirelength. +In almost all cases, these `pip` routeSegments exist in interconnect +tiles (which have names starting with the `INT` prefix) and are the only way for +signals to be routed between non-interconnect tiles. +Since `pip`s are the only type of routeSegment that can connect multiple tiles, all other types of +routeSegment (`belPin`, `sitePin`, `sitePIP`) are assumed to have a wirelength +of zero. Thus for a portion of a path that looks like this: ``` output belPin -> ... -> pip1 -> pip2 -> ... -> pipN -> ... -> input belPin 0 0 w x y z 0 0 @@ -66,7 +69,8 @@ The wirelength from the output to the input would be `w+x+y+z`. Each `pip` represents a connection that causes `wire0` to drive `wire1`; such connections incur a wirelength score based on the type of wire indicated by `wire1`. The following table presents regular expression patterns to be -matched against this `wire1` name and its associated wirelength score. +matched against the `wire1` name of PIPs with a tile name prefix of `INT` +and its associated wirelength score. | Wire Type | Regex Pattern | Wirelength Score | |-------------------|-------------------------|------------------| From 718a308ba4bb8764963d91cfd2050ffbd88f41d5 Mon Sep 17 00:00:00 2001 From: eddieh-xlnx Date: Mon, 30 Oct 2023 20:41:15 -0700 Subject: [PATCH 2/2] wirelength_analyzer to check PIP tile before assigning zero WL (#34) * wirelength_analyzer to check PIP tile before assigning zero WL Signed-off-by: Eddie Hung * Be more strict with 'INT_' prefix Signed-off-by: Eddie Hung * Add more tile names for in-context ispd16_example2 Signed-off-by: Eddie Hung * Rename variable Signed-off-by: Eddie Hung --------- Signed-off-by: Eddie Hung --- wirelength_analyzer/wa.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/wirelength_analyzer/wa.py b/wirelength_analyzer/wa.py index 9bc3971..329487a 100644 --- a/wirelength_analyzer/wa.py +++ b/wirelength_analyzer/wa.py @@ -18,6 +18,7 @@ import warnings import itertools from xcvup_device_data import xcvupDeviceData +import re class WirelengthAnalyzer: """ @@ -115,6 +116,7 @@ def __init__(self, netlist, verbosity=0): self.placements = {} for c in self.phys.placements: self.placements[(c.site, c.bel)] = c + self.tile_root_name_regex = re.compile(r'(.+)_X\d+Y\d+') self.add_all_nets_to_graph() def tstart(self): @@ -249,18 +251,23 @@ def segment_to_wirelength(self, seg): if seg.which() == 'pip': wire1 = seg.pip.wire1 tile = seg.pip.tile - - is_tile = self.tile_cache.get(tile) - if is_tile is None: - tile_name = self.phys.strList[tile] - is_tile = tile_name.startswith('INT') - self.tile_cache[tile] = is_tile - - if is_tile: + sl = self.phys.strList + + is_int_tile = self.tile_cache.get(tile) + if is_int_tile is None: + tile_name = sl[tile] + is_int_tile = tile_name.startswith('INT_') + self.tile_cache[tile] = is_int_tile + if not is_int_tile and self.tile_root_name_regex.match(tile_name).group(1) not in \ + ('CLEL_R', 'CLEM', 'CLEM_R', 'BRAM', 'DSP', + 'XIPHY_BYTE_L', 'HPIO_L', 'CMT_L'): + raise ValueError("Unrecognized tile on PIP: " + tile_name + ',' + sl[seg.pip.wire0] + ',' + sl[wire1]) + + if is_int_tile: wl = self.pip_cache.get(wire1) if wl is not None: return wl - wire1_name = self.phys.strList[wire1] + wire1_name = sl[wire1] for p in self.pips: if p[0].fullmatch(wire1_name): self.pip_cache[wire1] = p[1]