mirror of https://github.com/openXC7/prjxray.git
127 lines
4.5 KiB
Python
127 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# Copyright (C) 2017-2022 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
|
|
"""
|
|
SING-row IOB18 basic-config fuzzer design. For each IOB18 site that lives in a
|
|
*_SING tile, randomly instantiate OBUF / IBUF / nothing. The mix of driven,
|
|
input-only and unused sites gives segmaker the 0-reference it needs to resolve
|
|
the OUT / DRIVE / IN_USE bits (an all-output design leaves them const-1).
|
|
|
|
DRIVE / SLEW / PULLTYPE are applied to the ports by generate.tcl's loc_pins
|
|
from params.csv; the per-site type is recorded in params.jl for generate.py.
|
|
"""
|
|
import json
|
|
import os
|
|
import random
|
|
random.seed(int(os.getenv("SEED"), 16))
|
|
from prjxray import util
|
|
from prjxray import verilog
|
|
from prjxray.db import Database
|
|
|
|
# HP banks: low-voltage standards only.
|
|
IOSTANDARDS = ['LVCMOS12', 'LVCMOS15', 'LVCMOS18']
|
|
PULLS = ["NONE", "KEEPER", "PULLDOWN", "PULLUP"]
|
|
SLEWS = ['FAST', 'SLOW']
|
|
# OBUF (drive out), IBUF (input only) and unused, weighted toward variety.
|
|
TYPES = ['OBUF', 'OBUF', 'IBUF', 'IBUF', None, None]
|
|
|
|
|
|
def drives_for(iostandard):
|
|
if iostandard == 'LVCMOS12':
|
|
return [2, 4, 6, 8]
|
|
return [2, 4, 6, 8, 12, 16]
|
|
|
|
|
|
def gen_sites():
|
|
db = Database(util.get_db_root(), util.get_part())
|
|
grid = db.grid()
|
|
for tile_name in sorted(grid.tiles()):
|
|
gridinfo = grid.gridinfo_at_loc(grid.loc_of_tilename(tile_name))
|
|
if not gridinfo.tile_type.endswith("_SING"):
|
|
continue
|
|
for site_name, site_type in gridinfo.sites.items():
|
|
if site_type == 'IOB18':
|
|
yield tile_name, site_name
|
|
|
|
|
|
def main():
|
|
# One IOSTANDARD per specimen: all SING IOBs share it so a bank never sees
|
|
# conflicting VCCO (DRC BIVC-1). Variety across the N specimens gives
|
|
# process_rdb the LVCMOS12/15/18 set it merges into the DRIVE enum names.
|
|
iostandard = random.choice(IOSTANDARDS)
|
|
params = []
|
|
for tile, site in gen_sites():
|
|
params.append(
|
|
{
|
|
'tile': tile,
|
|
'site': site,
|
|
'type': random.choice(TYPES),
|
|
'IOSTANDARD': verilog.quote(iostandard),
|
|
'DRIVE': random.choice(drives_for(iostandard)),
|
|
'SLEW': verilog.quote(random.choice(SLEWS)),
|
|
'PULLTYPE': verilog.quote(random.choice(PULLS)),
|
|
})
|
|
|
|
# params.csv for generate.tcl's loc_pins (tile,site,pin,iostd,drive,slew,pull)
|
|
lines = ['tile,site,pin,iostandard,drive,slew,pulltype']
|
|
n_in = n_out = 0
|
|
for p in params:
|
|
if p['type'] == 'OBUF':
|
|
p['pin'] = 'do[{}]'.format(n_out)
|
|
n_out += 1
|
|
elif p['type'] == 'IBUF':
|
|
p['pin'] = 'di[{}]'.format(n_in)
|
|
n_in += 1
|
|
else:
|
|
p['pin'] = None
|
|
continue
|
|
lines.append(
|
|
','.join(
|
|
map(
|
|
str, (
|
|
p['tile'], p['site'], p['pin'],
|
|
verilog.unquote(p['IOSTANDARD']), p['DRIVE'],
|
|
verilog.unquote(p['SLEW']),
|
|
verilog.unquote(p['PULLTYPE'])))))
|
|
open('params.csv', 'w').write('\n'.join(lines) + '\n')
|
|
|
|
with open('params.jl', 'w') as f:
|
|
json.dump(params, f, indent=2)
|
|
|
|
# Verilog: one OBUF / IBUF per used site, LOC'd; unused sites get nothing.
|
|
# OBUFs are driven by a DONT_TOUCH LUT source (no external clock port, which
|
|
# would be an unplaceable terminal); DRIVE/SLEW/PULLTYPE come from loc_pins.
|
|
print('module top(output wire [{no}:0] do, input wire [{ni}:0] di);'.format(
|
|
no=max(n_out - 1, 0), ni=max(n_in - 1, 0)))
|
|
print(' wire src;')
|
|
print(' (* KEEP, DONT_TOUCH *) '
|
|
'LUT6 #(.INIT(64\'hAAAAAAAAAAAAAAAA)) srclut '
|
|
'(.O(src), .I0(1\'b0), .I1(1\'b0), .I2(1\'b0), '
|
|
'.I3(1\'b0), .I4(1\'b0), .I5(1\'b0));')
|
|
for idx, p in enumerate(params):
|
|
if p['type'] == 'OBUF':
|
|
print(
|
|
'''
|
|
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
|
OBUF obuf_{idx} (.I(src), .O({pin}));'''.format(
|
|
site=p['site'], idx=idx, pin=p['pin']))
|
|
elif p['type'] == 'IBUF':
|
|
print(
|
|
'''
|
|
wire ib_{idx};
|
|
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
|
|
IBUF ibuf_{idx} (.I({pin}), .O(ib_{idx}));'''.format(
|
|
site=p['site'], idx=idx, pin=p['pin']))
|
|
print('endmodule')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|