#!/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 import io import os import random import re random.seed(int(os.getenv("SEED"), 16)) from prjxray import util from prjxray import lut_maker from prjxray import verilog from prjxray.db import Database def gen_sites(): db = Database(util.get_db_root(), util.get_part()) grid = db.grid() for tile_name in sorted(grid.tiles()): loc = grid.loc_of_tilename(tile_name) gridinfo = grid.gridinfo_at_loc(loc) for site_name, site_type in gridinfo.sites.items(): if site_type in ['BSCAN', 'CAPTURE', 'ICAP', 'USR_ACCESS', 'STARTUP', 'FRAME_ECC', 'DCIRESET']: if site_name not in 'ICAP_X0Y0': yield site_name, site_type def write_csv_params(params): pinstr = 'tile,site,\n' for vals in params: pinstr += ','.join(map(str, vals)) + '\n' open('params.csv', 'w').write(pinstr) def generate_params(): bscan_already_on = False icap_already_on = False tile_params = [] for loci, (site, site_type) in enumerate(sorted(gen_sites())): p = {} if site_type in "ICAP" and not icap_already_on: p["ICAP_WIDTH"] = verilog.quote( random.choice(["X32", "X8", "X16"])) elif site_type in "BSCAN" and not bscan_already_on: p["JTAG_CHAIN"] = random.randint(1, 4) bscan_already_on = True elif site_type in "CAPTURE": p["ONESHOT"] = verilog.quote(random.choice(["TRUE", "FALSE"])) elif site_type in "STARTUP": p["PROG_USR"] = verilog.quote(random.choice(["TRUE", "FALSE"])) elif site_type in "FRAME_ECC": p["FARSRC"] = verilog.quote(random.choice(["FAR", "EFAR"])) elif site_type in [ "DCIRESET", "USR_ACCESS" ]: #The primitives from these sites have no parameters p["ENABLED"] = random.randint(0, 1) else: continue p["LOC"] = verilog.quote(site) tile_params.append( { "site": site, "site_type": site_type, "module": "mod_{}".format(site_type), "params": p }) return tile_params def generate_netlist(params): DUTN = len(params) DIN_N = DUTN * 32 DOUT_N = DUTN * 32 string_output = io.StringIO() any_bscan = False any_icap = False usr_access_on = False capture_on = False startup_on = False frame_ecc_on = False dcireset_on = False luts = lut_maker.LutMaker() verilog.top_harness(DIN_N, DOUT_N) print( ''' module roi(input clk, input [%d:0] din, output [%d:0] dout);''' % (DIN_N - 1, DOUT_N - 1)) for loci, param in enumerate(params): ports = { 'din': 'din[{} +: 8]'.format(8 * loci), 'dout': 'dout[{} +: 8]'.format(8 * loci), 'clk': 'clk' } if param["site_type"] in "BSCAN": ports = { 'din': '{{din[{} +: 7],{}}}'.format( 8 * loci + 1, luts.get_next_output_net()), 'dout': '{{dout[{} +: 7],{}}}'.format( 8 * loci + 1, luts.get_next_input_net()), 'clk': 'clk' } any_bscan = True elif param["site_type"] in ["ICAP"]: any_icap = True elif param["site_type"] in ["CAPTURE"]: capture_on = True elif param["site_type"] in ["STARTUP"]: startup_on = True elif param["site_type"] in ["FRAME_ECC"]: frame_ecc_on = True elif param["site_type"] in ["USR_ACCESS", "DCIRESET"]: if not param["params"]["ENABLED"]: continue if param["site_type"] in ["DCIRESET"]: dcireset_on = True else: usr_access_on = True else: continue verilog.instance( param["module"], "inst_{}".format(param["site"]), ports, param["params"], string_buffer=string_output) #Generate LUTs for l in luts.create_wires_and_luts(): print(l) print(string_output.getvalue()) print( ''' endmodule // ---------------------------------------------------------------------''') if any_icap: print( ''' module mod_ICAP (input [7:0] din, output [7:0] dout, input clk); parameter ICAP_WIDTH = "X32"; parameter LOC = "ICAP_X0Y0"; wire [23:0] icap_out; (* KEEP, DONT_TOUCH, LOC=LOC *) ICAPE2 #( .ICAP_WIDTH(ICAP_WIDTH), .SIM_CFG_FILE_NAME("NONE") ) ICAPE2_inst ( .O({icap_out, dout}), .CLK(clk), .CSIB(), .I({24'd0, din}), .RDWRB() ); endmodule ''') if capture_on: print( ''' module mod_CAPTURE (input [7:0] din, output [7:0] dout, input clk); parameter ONESHOT ="TRUE"; parameter LOC = "ICAP_X0Y0"; (* KEEP, DONT_TOUCH, LOC=LOC *) CAPTUREE2 #( .ONESHOT(ONESHOT) // Specifies the procedure for performing single readback per CAP trigger. ) CAPTUREE2_inst ( .CAP(1'b0), .CLK(clk) ); endmodule ''') if usr_access_on: print( ''' module mod_USR_ACCESS (input [7:0] din, output [7:0] dout, input clk); parameter ENABLED = 1; parameter LOC = "USR_ACCESS_X0Y0"; wire [23:0] usr_access_wire; (* KEEP, DONT_TOUCH, LOC=LOC *) USR_ACCESSE2 USR_ACCESSE2_inst ( .CFGCLK(), .DATA({usr_access_wire, dout}), .DATAVALID() ); endmodule ''') if any_bscan: print( ''' module mod_BSCAN (input [7:0] din, output [7:0] dout, input clk); parameter JTAG_CHAIN = 1; parameter LOC = "BSCAN_X0Y0"; (* KEEP, DONT_TOUCH, LOC=LOC *) BSCANE2 #( .JTAG_CHAIN(JTAG_CHAIN) ) dut ( .CAPTURE(), .DRCK(), .RESET(), .RUNTEST(), .SEL(), .SHIFT(), .TCK(), .TDI(dout[0]), .TMS(), .UPDATE(), .TDO(din[0]) ); endmodule ''') if startup_on: print( ''' module mod_STARTUP (input [7:0] din, output [7:0] dout, input clk); parameter LOC = "STARTUP_X0Y0"; parameter PROG_USR = "FALSE"; (* KEEP, DONT_TOUCH, LOC=LOC *) STARTUPE2 #( .PROG_USR(PROG_USR), // Activate program event security feature. Requires encrypted bitstreams. .SIM_CCLK_FREQ(0.0) // Set the Configuration Clock Frequency(ns) for simulation. ) STARTUPE2_inst ( .CFGCLK(), .CFGMCLK(), .EOS(), .PREQ(dout[0]), .CLK(clk), .GSR(), .GTS(), .KEYCLEARB(), .PACK(), .USRCCLKO(), .USRCCLKTS(), .USRDONEO(), .USRDONETS() ); endmodule ''') if frame_ecc_on: print( ''' module mod_FRAME_ECC (input [7:0] din, output [7:0] dout, input clk); parameter LOC = "FRAME_ECC_X0Y0"; parameter FARSRC = "EFAR"; wire [25:0] far_wire; assign dout[7:0] = far_wire[7:0]; (* KEEP, DONT_TOUCH, LOC=LOC *) FRAME_ECCE2 #( .FARSRC(FARSRC), .FRAME_RBT_IN_FILENAME("NONE") ) FRAME_ECCE2_inst ( .CRCERROR(), .ECCERROR(), .ECCERRORSINGLE(), .FAR(far_wire), .SYNBIT(), .SYNDROME(), .SYNDROMEVALID(), .SYNWORD() ); endmodule ''') if dcireset_on: print( ''' module mod_DCIRESET (input [7:0] din, output [7:0] dout, input clk); parameter LOC = "FRAME_ECC_X0Y0"; parameter ENABLED = 1; (* KEEP, DONT_TOUCH, LOC=LOC *) DCIRESET DCIRESET_inst ( .LOCKED(dout[0]), .RST(dout[1]) ); endmodule ''') def run(): params = generate_params() generate_netlist(params) with open('params.jl', 'w') as f: json.dump(params, f, indent=2) if __name__ == '__main__': run()