| #!/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 | 
 |  | 
 | import json | 
 |  | 
 | from prjxray.segmaker import Segmaker | 
 | from prjxray import verilog | 
 |  | 
 |  | 
 | def bitfilter(frame, word): | 
 |     if frame < 28: | 
 |         return False | 
 |  | 
 |     return True | 
 |  | 
 |  | 
 | def bus_tags(segmk, ps, site): | 
 |     segmk.add_site_tag(site, 'IN_USE', ps['active']) | 
 |  | 
 |     if not ps['active']: | 
 |         return | 
 |  | 
 |     for k in ps: | 
 |         segmk.add_site_tag(site, 'param_' + k + '_' + str(ps[k]), 1) | 
 |  | 
 |     for reg, invert in [ | 
 |         ('RST', 1), | 
 |         ('PWRDWN', 1), | 
 |         ('CLKINSEL', 0), | 
 |     ]: | 
 |         opt = 'IS_{}_INVERTED'.format(reg) | 
 |  | 
 |         if invert: | 
 |             segmk.add_site_tag(site, 'ZINV_' + reg, 1 ^ ps[opt]) | 
 |         else: | 
 |             segmk.add_site_tag(site, 'INV_' + reg, ps[opt]) | 
 |  | 
 |     for opt in ['OPTIMIZED', 'HIGH', 'LOW']: | 
 |         if verilog.unquote(ps['BANDWIDTH']) == opt: | 
 |             segmk.add_site_tag(site, 'BANDWIDTH.' + opt, 1) | 
 |         elif verilog.unquote(ps['BANDWIDTH']) == 'LOW': | 
 |             segmk.add_site_tag(site, 'BANDWIDTH.' + opt, 0) | 
 |  | 
 |     for opt in ['ZHOLD', 'BUF_IN', 'EXTERNAL', 'INTERNAL']: | 
 |         continue | 
 |  | 
 |         opt_match = verilog.unquote(ps['COMPENSATION']) == opt | 
 |  | 
 |         if ps['clkfbin_conn'] == '': | 
 |             segmk.add_site_tag(site, 'COMP.NOFB_' + opt, opt_match) | 
 |             segmk.add_site_tag(site, 'COMP.ZNOFB_' + opt, opt_match) | 
 |             continue | 
 |  | 
 |         for conn in ['clk', 'clkfbout_mult_BUFG_' + ps['site'], | 
 |                      'clkfbout_mult_' + ps['site']]: | 
 |             conn_match = ps['clkfbin_conn'] == conn | 
 |             segmk.add_site_tag( | 
 |                 site, 'COMP.' + opt + '_' + conn + '_' + ps['site'], opt_match | 
 |                 and conn_match) | 
 |             segmk.add_site_tag( | 
 |                 site, 'COMP.Z' + opt + '_' + conn + '_' + ps['site'], | 
 |                 not opt_match and conn_match) | 
 |             segmk.add_site_tag( | 
 |                 site, 'COMP.Z' + opt + '_Z' + conn + '_' + ps['site'], | 
 |                 not opt_match and not conn_match) | 
 |             segmk.add_site_tag( | 
 |                 site, 'COMP.' + opt + '_Z' + conn + '_' + ps['site'], opt_match | 
 |                 and not conn_match) | 
 |  | 
 |     bufg_on_clkin = \ | 
 |             'BUFG' in ps['clkin1_conn'] or \ | 
 |             'BUFG' in ps['clkin2_conn'] | 
 |  | 
 |     # This one is in conflict with some clock routing bits. | 
 |     #    match = verilog.unquote(ps['COMPENSATION']) in ['BUF_IN', 'EXTERNAL'] | 
 |     #    if not match: | 
 |     #        if verilog.unquote(ps['COMPENSATION']) == 'ZHOLD' and bufg_on_clkin: | 
 |     #            match = True | 
 |     #    segmk.add_site_tag( | 
 |     #        site, 'COMPENSATION.BUF_IN_OR_EXTERNAL_OR_ZHOLD_CLKIN_BUF', match) | 
 |  | 
 |     match = verilog.unquote(ps['COMPENSATION']) in ['ZHOLD'] | 
 |     segmk.add_site_tag( | 
 |         site, 'COMPENSATION.Z_ZHOLD_OR_CLKIN_BUF', not match | 
 |         or (match and bufg_on_clkin)) | 
 |     segmk.add_site_tag( | 
 |             site, 'COMPENSATION.ZHOLD_NO_CLKIN_BUF', match and \ | 
 |                     not bufg_on_clkin | 
 |                     ) | 
 |     segmk.add_site_tag( | 
 |             site, 'COMPENSATION.ZHOLD_NO_CLKIN_BUF_NO_TOP', match and \ | 
 |                     not bufg_on_clkin and \ | 
 |                     site != "PLLE2_ADV_X0Y3" and site != "PLLE2_ADV_X0Y0" | 
 |                     ) | 
 |     segmk.add_site_tag( | 
 |             site, 'COMP.ZHOLD_NO_CLKIN_BUF_TOP', match and \ | 
 |                     not bufg_on_clkin and \ | 
 |                     (site == "PLLE2_ADV_X0Y3" or site == "PLLE2_ADV_X0Y0") | 
 |                     ) | 
 |  | 
 |     # No INTERNAL as it has conflicting bits | 
 |     for opt in ['ZHOLD', 'BUF_IN', 'EXTERNAL']: | 
 |         if opt in ['BUF_IN', 'EXTERNAL']: | 
 |             if ps['clkfbin_conn'] not in ['', 'clk']: | 
 |                 continue | 
 |  | 
 |         if site == "PLLE2_ADV_X0Y2" and opt == 'ZHOLD': | 
 |             segmk.add_site_tag( | 
 |                 site, 'TOP.COMPENSATION.' + opt, | 
 |                 verilog.unquote(ps['COMPENSATION']) == opt) | 
 |         else: | 
 |             segmk.add_site_tag( | 
 |                 site, 'COMPENSATION.' + opt, | 
 |                 verilog.unquote(ps['COMPENSATION']) == opt) | 
 |         segmk.add_site_tag( | 
 |             site, 'COMPENSATION.Z_' + opt, | 
 |             verilog.unquote(ps['COMPENSATION']) != opt) | 
 |  | 
 |  | 
 | # This one has bits that are in conflict with clock routing | 
 | #    segmk.add_site_tag( | 
 | #        site, 'COMPENSATION.INTERNAL', | 
 | #        verilog.unquote(ps['COMPENSATION']) in ['INTERNAL']) | 
 |  | 
 |     for param in ['CLKFBOUT_MULT']: | 
 |         paramadj = int(ps[param]) | 
 |         bitstr = [int(x) for x in "{0:09b}".format(paramadj)[::-1]] | 
 |         for i in range(7): | 
 |             segmk.add_site_tag(site, '%s[%u]' % (param, i), bitstr[i]) | 
 |  | 
 |     for param in ['CLKOUT0_DUTY_CYCLE']: | 
 |         assert ps[param][:2] == '0.', ps[param] | 
 |         assert len(ps[param]) == 5 | 
 |         paramadj = int(ps[param][2:]) | 
 |         bitstr = [int(x) for x in "{0:011b}".format(paramadj)[::-1]] | 
 |  | 
 |         for i in range(10): | 
 |             segmk.add_site_tag(site, '%s[%u]' % (param, i), bitstr[i]) | 
 |  | 
 |     for param, bits in [ | 
 |         ('CLKOUT0_DIVIDE', 7), | 
 |         ('CLKOUT1_DIVIDE', 7), | 
 |         ('CLKOUT2_DIVIDE', 7), | 
 |         ('CLKOUT3_DIVIDE', 7), | 
 |         ('CLKOUT4_DIVIDE', 7), | 
 |         ('CLKOUT5_DIVIDE', 7), | 
 |         ('DIVCLK_DIVIDE', 6), | 
 |     ]: | 
 |         # 1-128 => 0-127 for actual 7 bit value | 
 |         paramadj = int(ps[param]) | 
 |         if paramadj < 4: | 
 |             continue | 
 |  | 
 |         bitstr = [int(x) for x in "{0:09b}".format(paramadj)[::-1]] | 
 |         for i in range(bits): | 
 |             segmk.add_site_tag(site, '%s[%u]' % (param, i), bitstr[i]) | 
 |  | 
 |     segmk.add_site_tag( | 
 |         site, 'STARTUP_WAIT', | 
 |         verilog.unquote(ps['STARTUP_WAIT']) == 'TRUE') | 
 |  | 
 |  | 
 | def run(): | 
 |  | 
 |     segmk = Segmaker("design.bits") | 
 |  | 
 |     print("Loading tags") | 
 |     f = open('params.jl', 'r') | 
 |     f.readline() | 
 |     for l in f: | 
 |         j = json.loads(l) | 
 |         bus_tags(segmk, j, j['site']) | 
 |  | 
 |     segmk.compile(bitfilter=bitfilter) | 
 |     segmk.write() | 
 |  | 
 |  | 
 | run() |