| #!/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() |