mirror of https://github.com/openXC7/prjxray.git
133 lines
3.7 KiB
Python
133 lines
3.7 KiB
Python
#!/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()
|