|  | #!/usr/bin/env python3 | 
|  | # -*- coding: utf-8 -*- | 
|  | # | 
|  | # Copyright (C) 2017-2020  The Project X-Ray Authors. | 
|  | # | 
|  | # Use of this source code is governed by a ISC-style | 
|  | # license that can be found in the LICENSE file or at | 
|  | # https://opensource.org/licenses/ISC | 
|  | # | 
|  | # SPDX-License-Identifier: ISC | 
|  | # | 
|  | # Produces a complete database of wires in the ROI and their connections and tests if each | 
|  | # routing node is a tree (i.e. fails with an error when a loop is found). | 
|  |  | 
|  | import os, sys, json | 
|  |  | 
|  | from prjxray.util import OpenSafeFile | 
|  |  | 
|  | def main(): | 
|  | with OpenSafeFile("%s/%s/tilegrid.json" % (os.getenv("XRAY_DATABASE_DIR"), | 
|  | os.getenv("XRAY_DATABASE")), "r") as f: | 
|  | tilegrid = json.load(f) | 
|  |  | 
|  | with OpenSafeFile("%s/%s/tileconn.json" % (os.getenv("XRAY_DATABASE_DIR"), | 
|  | os.getenv("XRAY_DATABASE")), "r") as f: | 
|  | tileconn = json.load(f) | 
|  |  | 
|  | grid = dict() | 
|  | wirepairs = dict() | 
|  | remwires = set() | 
|  |  | 
|  | for tilename, tiledata in tilegrid.items(): | 
|  | key = (tiledata["grid_x"], tiledata["grid_y"]) | 
|  | grid[key] = tilename | 
|  |  | 
|  | def check_tileconn_entry(tilename, tiledata, entry, idx): | 
|  | if idx == 0: | 
|  | otheridx = 1 | 
|  | otherxy = ( | 
|  | tiledata["grid_x"] + entry["grid_deltas"][0], | 
|  | tiledata["grid_y"] + entry["grid_deltas"][1]) | 
|  | else: | 
|  | otheridx = 0 | 
|  | otherxy = ( | 
|  | tiledata["grid_x"] - entry["grid_deltas"][0], | 
|  | tiledata["grid_y"] - entry["grid_deltas"][1]) | 
|  |  | 
|  | if otherxy not in grid: | 
|  | return | 
|  |  | 
|  | othertilename = grid[otherxy] | 
|  | othertiledata = tilegrid[othertilename] | 
|  |  | 
|  | if othertiledata["type"] != entry["tile_types"][otheridx]: | 
|  | return | 
|  |  | 
|  | print( | 
|  | "  Found relevant entry (%s %s %d %d): %s" % ( | 
|  | entry["tile_types"][0], entry["tile_types"][1], | 
|  | entry["grid_deltas"][0], entry["grid_deltas"][1], | 
|  | othertilename)) | 
|  |  | 
|  | for pair in entry["wire_pairs"]: | 
|  | wirename = "%s/%s" % (tilename, pair[idx]) | 
|  | otherwirename = "%s/%s" % (othertilename, pair[otheridx]) | 
|  |  | 
|  | remwires.add(wirename) | 
|  | remwires.add(otherwirename) | 
|  |  | 
|  | if wirename not in wirepairs: | 
|  | wirepairs[wirename] = set() | 
|  | wirepairs[wirename].add(otherwirename) | 
|  |  | 
|  | if otherwirename not in wirepairs: | 
|  | wirepairs[otherwirename] = set() | 
|  | wirepairs[otherwirename].add(wirename) | 
|  |  | 
|  | for tilename, tiledata in tilegrid.items(): | 
|  | print("Connecting wires in tile %s." % tilename) | 
|  | for entry in tileconn: | 
|  | if entry["tile_types"][0] == tiledata["type"]: | 
|  | check_tileconn_entry(tilename, tiledata, entry, 0) | 
|  | if entry["tile_types"][1] == tiledata["type"]: | 
|  | check_tileconn_entry(tilename, tiledata, entry, 1) | 
|  |  | 
|  | def check_wire(wire, source): | 
|  | for next_wire in wirepairs[wire]: | 
|  | if next_wire == source: | 
|  | continue | 
|  | print("  %s" % next_wire) | 
|  | if next_wire not in remwires: | 
|  | print("  ** FOUND LOOP IN THIS NODE **") | 
|  | sys.exit(1) | 
|  | remwires.remove(next_wire) | 
|  | check_wire(next_wire, wire) | 
|  |  | 
|  | while len(remwires): | 
|  | wire = remwires.pop() | 
|  | print("Checking %s:" % wire) | 
|  | check_wire(wire, None) | 
|  |  | 
|  | print("NO LOOP FOUND: OK") | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | main() |