#!/usr/bin/env python3 # # Copyright (C) 2015 Clifford Wolf # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # import icebox from icebox import re_match_cached import getopt, sys, re, os check_mode = False fixup_mode = False def usage(): print(""" Usage: %s [options] [input.asc [output.asc]] -c check colbuf bits -f fix colbuf bits """ % os.path.basename(sys.argv[0])) sys.exit(1) try: opts, args = getopt.getopt(sys.argv[1:], "cf") except: usage() for o, a in opts: if o == "-c": check_mode = True elif o == "-f": fixup_mode = True else: usage() if len(args) == 0: args.append("/dev/stdin") if len(args) not in [1, 2]: usage() if check_mode == fixup_mode: print("Error: Use either -c or -f!") sys.exit(1) print("Reading file '%s'.." % args[0]) ic = icebox.iceconfig() ic.read_file(args[0]) def make_cache(stmt, raw_db): cache = list() for entry in raw_db: if entry[1] == stmt and entry[2].startswith("glb_netwk_"): cache_entry = [int(entry[2][-1]), []] for bit in entry[0]: value = "1" if bit.startswith("!"): value = "0" bit = bit[1:] match = re_match_cached("B([0-9]+)\[([0-9]+)\]", bit) cache_entry[1].append((int(match.group(1)), int(match.group(2)), value)) cache.append(cache_entry) return cache def match_cache_entry(cache_entry, tile_dat): for entry in cache_entry[1]: if tile_dat[entry[0]][entry[1]] != entry[2]: return False return True def analyze_tile(ic, cache, tile_pos): glbs = set() tile_dat = ic.tile(tile_pos[0], tile_pos[1]) for cache_entry in cache: if match_cache_entry(cache_entry, tile_dat): glbs.add(cache_entry[0]) return glbs colbuf_map = dict() used_glbs_map = dict() driven_glbs_map = dict() for entry in ic.colbuf_db(): colbuf_map[(entry[2], entry[3])] = (entry[0], entry[1]) for tiles in [ic.io_tiles, ic.logic_tiles, ic.ramb_tiles, ic.ramt_tiles]: cache = None for tile in tiles: if cache is None: cache = make_cache("buffer", ic.tile_db(tile[0], tile[1])) glbs = analyze_tile(ic, cache, tile) if len(glbs): assert tile in colbuf_map s = used_glbs_map.setdefault(colbuf_map[tile], set()) used_glbs_map[colbuf_map[tile]] = s.union(glbs) cache = None for tile in tiles: if cache is None: cache = make_cache("ColBufCtrl", ic.tile_db(tile[0], tile[1])) glbs = analyze_tile(ic, cache, tile) if len(glbs): driven_glbs_map[tile] = glbs def set_colbuf(ic, tile, bit, value): tile_dat = ic.tile(tile[0], tile[1]) tile_db = ic.tile_db(tile[0], tile[1]) for entry in tile_db: if entry[1] == "ColBufCtrl" and entry[2] == "glb_netwk_%d" % bit: match = re_match_cached("B([0-9]+)\[([0-9]+)\]", entry[0][0]) l = tile_dat[int(match.group(1))] n = int(match.group(2)) l = l[:n] + value + l[n+1:] tile_dat[int(match.group(1))] = l return assert False error_count = 0 correct_count = 0 for tile, bits in sorted(used_glbs_map.items()): for bit in bits: if tile not in driven_glbs_map or bit not in driven_glbs_map[tile]: print("Missing driver for glb_netwk_%d in tile %s" % (bit, tile)) set_colbuf(ic, tile, bit, "1") error_count += 1 for tile, bits in sorted(driven_glbs_map.items()): for bit in bits: if tile not in used_glbs_map or bit not in used_glbs_map[tile]: print("Unused driver for glb_netwk_%d in tile %s" % (bit, tile)) set_colbuf(ic, tile, bit, "0") error_count += 1 else: # print("Correct driver for glb_netwk_%d in tile %s" % (bit, tile)) correct_count += 1 print("Found %d correct driver bits." % correct_count) if error_count != 0: if not fixup_mode: print("Found %d errors!" % error_count) sys.exit(1) ic.write_file(args[0] if len(args) == 1 else args[1]) print("Corrected %d errors." % error_count) else: print("No errors found.")