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