| #!/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, all_params, site): |
| segmk.add_site_tag(site, 'IN_USE', ps['active']) |
| |
| if not ps['active']: |
| return |
| |
| params = all_params[site]["params"] |
| |
| #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), |
| ('PSEN', 1), |
| ('PSINCDEC', 1), |
| ]: |
| 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) |
| |
| # "INTERNAL" compensation conflicts with the CLKFBOUT2IN->CLKFBIN PIP. |
| # There is no telling which of these two is actually controlled by those |
| # bits. It is better to leave them for the PIP. |
| COMPENSATION_OPTS = ['ZHOLD', 'BUF_IN', 'EXTERNAL'] |
| |
| for opt in COMPENSATION_OPTS: |
| val = params["COMPENSATION"] == opt |
| segmk.add_site_tag(site, "COMP.{}".format(opt), val) |
| segmk.add_site_tag(site, "COMP.Z_{}".format(opt), not val) |
| |
| opt = (verilog.unquote(ps["SS_EN"]) == "TRUE") |
| segmk.add_site_tag(site, "SS_EN", opt) |
| |
| for param in ['CLKFBOUT_MULT_F']: |
| 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_F', 7), |
| ('CLKOUT1_DIVIDE', 7), |
| ('CLKOUT2_DIVIDE', 7), |
| ('CLKOUT3_DIVIDE', 7), |
| ('CLKOUT4_DIVIDE', 7), |
| ('CLKOUT5_DIVIDE', 7), |
| ('CLKOUT6_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 params") |
| f = open("params.json") |
| params = json.load(f) |
| params = {p["site"]: p for p in params} |
| |
| print("Loading tags") |
| f = open('params.jl', 'r') |
| f.readline() |
| for l in f: |
| j = json.loads(l) |
| bus_tags(segmk, j, params, j['site']) |
| |
| segmk.compile(bitfilter=bitfilter) |
| segmk.write() |
| |
| |
| run() |