|  | #!/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() |