| #!/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 |
| |
| from prjxray.segmaker import Segmaker |
| from prjxray import verilog |
| import json |
| |
| # Set to true to enable additional tags useful for tracing bit toggles. |
| DEBUG_FUZZER = False |
| |
| |
| def bitfilter(frame, word): |
| if frame < 25 or frame > 31: |
| return False |
| |
| return True |
| |
| |
| def handle_data_width(segmk, d): |
| if 'DATA_WIDTH' not in d: |
| return |
| |
| site = d['ilogic_loc'] |
| |
| # It appears several widths end up with the same bitstream pattern. |
| # This groups those widths together for documentation. |
| widths = [ |
| [2], |
| [3], |
| [4, 6], |
| [5, 7], |
| [8], |
| [10], |
| [14], |
| ] |
| |
| width_map = {} |
| |
| for ws in widths: |
| for w in ws: |
| width_map[w] = 'W{}'.format('_'.join(map(str, ws))) |
| |
| zero_opt = 2 |
| W_OPT_ZERO = width_map[zero_opt] |
| if d['DATA_WIDTH'] == zero_opt: |
| segmk.add_site_tag(site, 'ISERDES.DATA_WIDTH.{}'.format(W_OPT_ZERO), 1) |
| |
| for opt in width_map.values(): |
| if opt == W_OPT_ZERO: |
| continue |
| |
| segmk.add_site_tag(site, 'ISERDES.DATA_WIDTH.{}'.format(opt), 0) |
| else: |
| w_opt = width_map[d['DATA_WIDTH']] |
| if w_opt != W_OPT_ZERO: |
| segmk.add_site_tag( |
| site, 'ISERDES.DATA_WIDTH.{}'.format(W_OPT_ZERO), 0) |
| segmk.add_site_tag(site, 'ISERDES.DATA_WIDTH.{}'.format(w_opt), 1) |
| |
| |
| def handle_data_rate(segmk, d): |
| if 'DATA_WIDTH' not in d: |
| return |
| |
| site = d['ilogic_loc'] |
| |
| for opt in ['SDR', 'DDR']: |
| segmk.add_site_tag( |
| site, 'ISERDES.DATA_RATE.{}'.format(opt), |
| verilog.unquote(d['DATA_RATE']) == opt) |
| |
| |
| def main(): |
| print("Loading tags") |
| segmk = Segmaker("design.bits") |
| |
| with open('params.jl', 'r') as f: |
| design = json.load(f) |
| |
| for d in design: |
| site = d['ilogic_loc'] |
| |
| handle_data_width(segmk, d) |
| handle_data_rate(segmk, d) |
| |
| segmk.add_site_tag(site, 'ISERDES.IN_USE', d['use_iserdese2']) |
| |
| if 'NUM_CE' in d: |
| segmk.add_site_tag(site, 'ISERDES.NUM_CE.N2', d['NUM_CE'] == 2) |
| |
| segmk.add_site_tag( |
| site, 'IDDR_OR_ISERDES.IN_USE', d['use_iserdese2'] |
| or d['iddr_mux_config'] != 'none') |
| |
| if 'INTERFACE_TYPE' in d: |
| for opt in ( |
| 'MEMORY', |
| 'MEMORY_DDR3', |
| 'MEMORY_QDR', |
| 'NETWORKING', |
| 'OVERSAMPLE', |
| ): |
| segmk.add_site_tag( |
| site, 'ISERDES.INTERFACE_TYPE.{}'.format(opt), |
| opt == verilog.unquote(d['INTERFACE_TYPE'])) |
| segmk.add_site_tag( |
| site, 'ISERDES.INTERFACE_TYPE.Z_{}'.format(opt), |
| opt != verilog.unquote(d['INTERFACE_TYPE'])) |
| |
| segmk.add_site_tag( |
| site, 'ISERDES.INTERFACE_TYPE.NOT_MEMORY', |
| 'MEMORY' not in verilog.unquote(d['INTERFACE_TYPE'])) |
| |
| if d['iddr_mux_config'] != 'none': |
| segmk.add_site_tag(site, 'IFF.ZINIT_Q1', not d['INIT_Q1']) |
| segmk.add_site_tag(site, 'IFF.ZINIT_Q2', not d['INIT_Q2']) |
| |
| if 'DYN_CLKDIV_INV_EN' in d: |
| segmk.add_site_tag( |
| site, 'DYN_CLKDIV_INV_EN', |
| verilog.unquote(d['DYN_CLKDIV_INV_EN']) == 'TRUE') |
| |
| if 'DYN_CLK_INV_EN' in d: |
| segmk.add_site_tag( |
| site, 'DYN_CLK_INV_EN', |
| verilog.unquote(d['DYN_CLK_INV_EN']) == 'TRUE') |
| |
| if 'INIT_Q3' in d: |
| segmk.add_site_tag(site, 'IFF.ZINIT_Q3', not d['INIT_Q3']) |
| segmk.add_site_tag(site, 'IFF.ZINIT_Q4', not d['INIT_Q4']) |
| segmk.add_site_tag( |
| site, 'IFF.ZSRVAL_Q1', not d['SRVAL_Q1']) |
| segmk.add_site_tag( |
| site, 'IFF.ZSRVAL_Q2', not d['SRVAL_Q2']) |
| segmk.add_site_tag( |
| site, 'IFF.ZSRVAL_Q3', not d['SRVAL_Q3']) |
| segmk.add_site_tag( |
| site, 'IFF.ZSRVAL_Q4', not d['SRVAL_Q4']) |
| |
| if 'IS_CLK_INVERTED' in d and not d['DISABLE_CLOCKS']: |
| if verilog.unquote(d['INTERFACE_TYPE']) == 'MEMORY_DDR3': |
| segmk.add_site_tag( |
| site, 'IFF.INV_CLK', d['IS_CLK_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.INV_CLKB', d['IS_CLKB_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLK', not d['IS_CLK_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLKB', not d['IS_CLKB_INVERTED']) |
| |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLK_XOR', |
| d['IS_CLK_INVERTED'] ^ d['IS_CLKB_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLK_NXOR', |
| not (d['IS_CLK_INVERTED'] ^ d['IS_CLKB_INVERTED'])) |
| |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLK_OR', d['IS_CLK_INVERTED'] |
| or d['IS_CLKB_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLK_NOR', not ( |
| d['IS_CLK_INVERTED'] or d['IS_CLKB_INVERTED'])) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLK_AND', d['IS_CLK_INVERTED'] |
| and d['IS_CLKB_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLK_NAND', not ( |
| d['IS_CLK_INVERTED'] |
| and d['IS_CLKB_INVERTED'])) |
| |
| if 'IS_OCLK_INVERTED' in d and not d['DISABLE_CLOCKS']: |
| segmk.add_site_tag( |
| site, 'IFF.INV_OCLK', d['IS_OCLK_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_OCLK', not d['IS_OCLK_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.INV_OCLKB', d['IS_OCLKB_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_OCLKB', not d['IS_OCLKB_INVERTED']) |
| |
| if 'IS_CLKDIV_INVERTED' in d and not d['DISABLE_CLOCKS'] and \ |
| verilog.unquote(d['INTERFACE_TYPE']) == 'MEMORY': |
| segmk.add_site_tag( |
| site, 'IFF.INV_CLKDIV', d['IS_CLKDIV_INVERTED']) |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_CLKDIV', not d['IS_CLKDIV_INVERTED']) |
| |
| if 'IS_C_INVERTED' in d: |
| segmk.add_site_tag( |
| site, 'IFF.ZINV_C', not d['IS_C_INVERTED']) |
| |
| segmk.add_site_tag(site, 'ZINV_D', not d['IS_D_INVERTED']) |
| |
| if 'SRTYPE' in d: |
| for opt in ['ASYNC', 'SYNC']: |
| segmk.add_site_tag( |
| site, 'IFF.SRTYPE.{}'.format(opt), |
| verilog.unquote(d['SRTYPE']) == opt) |
| |
| if 'DDR_CLK_EDGE' in d: |
| for opt in ['OPPOSITE_EDGE', 'SAME_EDGE', |
| 'SAME_EDGE_PIPELINED']: |
| segmk.add_site_tag( |
| site, 'IFF.DDR_CLK_EDGE.{}'.format(opt), |
| verilog.unquote(d['DDR_CLK_EDGE']) == opt) |
| |
| if d['iddr_mux_config'] == 'direct': |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P0', 0) |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P1', 1) |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P2', 0) |
| elif d['iddr_mux_config'] == 'idelay': |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P0', 1) |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P1', 0) |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P2', 0) |
| elif d['iddr_mux_config'] == 'none': |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P0', 0) |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P1', 0) |
| segmk.add_site_tag(site, 'IFFDELMUXE3.P2', 0) |
| else: |
| assert False, d['mux_config'] |
| |
| if d['mux_config'] == 'direct': |
| segmk.add_site_tag(site, 'IDELMUXE3.P0', 0) |
| segmk.add_site_tag(site, 'IDELMUXE3.P1', 1) |
| segmk.add_site_tag(site, 'IDELMUXE3.P2', 0) |
| |
| elif d['mux_config'] == 'idelay': |
| segmk.add_site_tag(site, 'IDELMUXE3.P0', 1) |
| segmk.add_site_tag(site, 'IDELMUXE3.P1', 0) |
| segmk.add_site_tag(site, 'IDELMUXE3.P2', 0) |
| |
| elif d['mux_config'] == 'none': |
| segmk.add_site_tag(site, 'IDELMUXE3.P0', 0) |
| segmk.add_site_tag(site, 'IDELMUXE3.P1', 0) |
| segmk.add_site_tag(site, 'IDELMUXE3.P2', 0) |
| else: |
| assert False, d['mux_config'] |
| |
| if DEBUG_FUZZER: |
| for k in d: |
| segmk.add_site_tag( |
| site, 'param_' + k + '_' + str(d[k]).replace( |
| ' ', '').replace('\n', ''), 1) |
| |
| segmk.compile(bitfilter=bitfilter) |
| segmk.write(allow_empty=True) |
| |
| |
| if __name__ == "__main__": |
| main() |