| #!/usr/bin/env python3 | |
| # | |
| # Copyright (C) 2015 Clifford Wolf <clifford@clifford.at> | |
| # | |
| # 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 | |
| import getopt, sys, re | |
| check_mode = False | |
| fixup_mode = False | |
| def usage(): | |
| print(""" | |
| Usage: icebox_colbuf [options] [input.asc [output.asc]] | |
| -c | |
| check colbuf bits | |
| -f | |
| fix colbuf bits | |
| """) | |
| 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("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("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.") | |