#!/usr/bin/env python3 from prjxray.segmaker import Segmaker from prjxray.db import Database from prjxray.util import get_db_root import re REBUF_GCLK = re.compile('^CLK_BUFG_REBUF_R_CK_GCLK([0-9]+)_BOT$') GCLKS = 32 def gclk_of_wire(wire): m = REBUF_GCLK.match(wire) assert m, wire return int(m.group(1)) class ClockColumn(object): def __init__(self, db_root): db = Database(db_root) grid = db.grid() tiles_in_gclk_columns = [] self.gclk_columns = {} for tile in grid.tiles(): gridinfo = grid.gridinfo_at_tilename(tile) if gridinfo.tile_type != 'CLK_BUFG_REBUF': continue loc = grid.loc_of_tilename(tile) tiles_in_gclk_columns.append((loc.grid_y, tile)) _, self.tiles_in_gclk_columns = zip( *sorted(tiles_in_gclk_columns, key=lambda x: x[0])) # Initially all GCLK lines are idle. GCLK lines only exist between #CLK_BUFG_REBUF tiles, hence len-1. for gclk in range(GCLKS): self.gclk_columns[gclk] = [ False for _ in range(len(self.tiles_in_gclk_columns) - 1) ] def enable_rebuf(self, tile, wire): # Find which REBUF is being activated. rebuf_idx = self.tiles_in_gclk_columns.index(tile) assert rebuf_idx != -1, tile gclk = gclk_of_wire(wire) self.gclk_columns[gclk][rebuf_idx] = True self.gclk_columns[gclk][rebuf_idx - 1] = True def yield_rebuf_state(self): """ Yields tile_name, gclk, bool if active above tile, bool if active below tile """ for idx, tile in enumerate(self.tiles_in_gclk_columns): for gclk in range(GCLKS): active_below = False active_above = False if idx > 0: active_below = self.gclk_columns[gclk][idx - 1] if idx < len(self.gclk_columns[gclk]): active_above = self.gclk_columns[gclk][idx] yield tile, gclk, active_below, active_above def main(): db_root = get_db_root() clock_column = ClockColumn(db_root) segmk = Segmaker("design.bits") print("Loading tags from design.txt.") with open("route.txt", "r") as f: for line in f: if 'CLK_BUFG_REBUF' not in line: continue parts = line.replace('{', '').replace('}', '').strip().replace( '\t', ' ').split(' ') dst = parts[0] pip = parts[3] tile_from_pip, pip = pip.split('/') if 'CLK_BUFG_REBUF' not in tile_from_pip: continue tile_type, pip = pip.split('.') assert tile_type == 'CLK_BUFG_REBUF' wire_a, wire_b = pip.split('<<->>') tile_from_wire, dst = dst.split('/') assert dst == wire_a if tile_from_wire == tile_from_pip: b_to_a = wire_a == dst a_to_b = not b_to_a else: b_to_a = wire_a != dst a_to_b = not b_to_a segmk.add_tile_tag( tile_from_pip, '{}.{}'.format(wire_a, wire_b), b_to_a) segmk.add_tile_tag( tile_from_pip, '{}.{}'.format(wire_b, wire_a), a_to_b) clock_column.enable_rebuf(tile_from_pip, wire_a) for tile, gclk, active_below, active_above in clock_column.yield_rebuf_state( ): segmk.add_tile_tag( tile, 'GCLK{}_ENABLE_ABOVE'.format(gclk), active_above) segmk.add_tile_tag( tile, 'GCLK{}_ENABLE_BELOW'.format(gclk), active_below) segmk.compile() segmk.write(allow_empty=True) if __name__ == '__main__': main()