mirror of https://github.com/openXC7/prjxray.git
318 lines
7.9 KiB
Python
318 lines
7.9 KiB
Python
#!/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()
|