mirror of https://github.com/openXC7/prjxray.git
Merge pull request #614 from antmicro/030-iob
iob: enhance fuzzer with bits for SLEW and DRIVE for LVCMOS25
This commit is contained in:
commit
3872d414cc
|
|
@ -1,2 +1,12 @@
|
||||||
38_92 39_93 38_94,LIOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
38_92 39_93 38_94,LIOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
||||||
|
38_118 38_126 39_117 39_119 39_125 39_127,LIOB33.IOB_Y0.LVCMOS25.DRIVE.12
|
||||||
|
38_106 38_110 39_105 39_109,LIOB33.IOB_Y0.SLEW.FAST
|
||||||
39_33 38_34 39_35,LIOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
39_33 38_34 39_35,LIOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
||||||
|
38_00 38_02 38_08 38_10 39_01 39_09,LIOB33.IOB_Y1.LVCMOS25.DRIVE.12
|
||||||
|
38_18 38_22 39_17 39_21,LIOB33.IOB_Y1.SLEW.FAST
|
||||||
|
38_92 39_93 38_94,RIOB33.IOB_Y0.PULLTYPE.PULLDOWN
|
||||||
|
38_118 38_126 39_117 39_119 39_125 39_127,RIOB33.IOB_Y0.LVCMOS25.DRIVE.12
|
||||||
|
38_106 38_110 39_105 39_109,RIOB33.IOB_Y0.SLEW.FAST
|
||||||
|
39_33 38_34 39_35,RIOB33.IOB_Y1.PULLTYPE.PULLDOWN
|
||||||
|
38_00 38_02 38_08 38_10 39_01 39_09,RIOB33.IOB_Y1.LVCMOS25.DRIVE.12
|
||||||
|
38_18 38_22 39_17 39_21,RIOB33.IOB_Y1.SLEW.FAST
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ segmk = Segmaker("design.bits")
|
||||||
|
|
||||||
print("Loading tags")
|
print("Loading tags")
|
||||||
'''
|
'''
|
||||||
port,site,tile,pin,val
|
port,site,tile,pin,slew,drive,pulltype
|
||||||
di[0],IOB_X0Y107,LIOB33_X0Y107,A21,PULLDOWN
|
di[0],IOB_X0Y107,LIOB33_X0Y107,A21,PULLDOWN
|
||||||
di[10],IOB_X0Y147,LIOB33_X0Y147,F14,PULLUP
|
di[10],IOB_X0Y147,LIOB33_X0Y147,F14,PULLUP
|
||||||
'''
|
'''
|
||||||
|
|
@ -15,19 +15,35 @@ f = open('design.csv', 'r')
|
||||||
f.readline()
|
f.readline()
|
||||||
for l in f:
|
for l in f:
|
||||||
l = l.strip()
|
l = l.strip()
|
||||||
port, site, tile, pin, val = l.split(',')
|
port, site, tile, pin, iostandard, slew, drive, pulltype = l.split(',')
|
||||||
'''
|
'''
|
||||||
|
LVCMOS25
|
||||||
|
SLEW 38_82 38_86 39_81 39_85
|
||||||
|
SLOW X X X X
|
||||||
|
FAST
|
||||||
|
|
||||||
|
DRIVE 38_64 38_66 38_72 38_74 39_65 39_73
|
||||||
|
4 X X X
|
||||||
|
8 X
|
||||||
|
12
|
||||||
|
16 X X X
|
||||||
|
|
||||||
PULLTYPE 28 29 30
|
PULLTYPE 28 29 30
|
||||||
NONE X
|
NONE X
|
||||||
KEEPER X X
|
KEEPER X X
|
||||||
PULLDOWN
|
PULLDOWN
|
||||||
PULLUP X X
|
PULLUP X X
|
||||||
'''
|
'''
|
||||||
if val == "":
|
if pulltype == "":
|
||||||
val = "NONE"
|
pulltype = "NONE"
|
||||||
segmaker.add_site_group_zero(
|
segmaker.add_site_group_zero(
|
||||||
segmk, site, "PULLTYPE.", ("NONE", "KEEPER", "PULLDOWN", "PULLUP"),
|
segmk, site, "PULLTYPE.", ("NONE", "KEEPER", "PULLDOWN", "PULLUP"),
|
||||||
"PULLDOWN", val)
|
"PULLDOWN", pulltype)
|
||||||
|
|
||||||
|
segmaker.add_site_group_zero(
|
||||||
|
segmk, site, iostandard + ".DRIVE.", ("4", "8", "12", "16"), "12",
|
||||||
|
drive)
|
||||||
|
segmaker.add_site_group_zero(
|
||||||
|
segmk, site, "SLEW.", ("SLOW", "FAST"), "FAST", slew)
|
||||||
segmk.compile()
|
segmk.compile()
|
||||||
segmk.write()
|
segmk.write()
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ proc loc_pins {} {
|
||||||
set io_pin_sites [make_io_pin_sites]
|
set io_pin_sites [make_io_pin_sites]
|
||||||
|
|
||||||
set fp [open "design.csv" w]
|
set fp [open "design.csv" w]
|
||||||
puts $fp "port,site,tile,pin,val"
|
puts $fp "port,site,tile,pin,iostandard,slew,drive,pulltype"
|
||||||
|
|
||||||
puts "Looping"
|
puts "Looping"
|
||||||
for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
|
for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
|
||||||
|
|
@ -53,20 +53,27 @@ proc loc_pins {} {
|
||||||
set tile [get_tiles -of_objects $site]
|
set tile [get_tiles -of_objects $site]
|
||||||
set pin [dict get $io_pin_sites $site]
|
set pin [dict get $io_pin_sites $site]
|
||||||
|
|
||||||
set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS33" $port
|
set iostandard_val "LVCMOS25"
|
||||||
|
set_property -dict "PACKAGE_PIN $pin IOSTANDARD $iostandard_val" $port
|
||||||
|
|
||||||
# list_property isn't working (maybe due to empty?)
|
set pulltype "NONE PULLUP PULLDOWN KEEPER"
|
||||||
# set keys [list_property_value PULLTYPE $port]
|
set pulltype_val [randsample_list 1 $pulltype]
|
||||||
# NONE placeholder for ""
|
if { $pulltype_val == "NONE" } {
|
||||||
set keys "NONE PULLUP PULLDOWN KEEPER"
|
set pulltype_val ""
|
||||||
set val [randsample_list 1 $keys]
|
|
||||||
if { $val == "NONE" } {
|
|
||||||
set val ""
|
|
||||||
}
|
}
|
||||||
|
set_property PULLTYPE $pulltype_val $port
|
||||||
|
|
||||||
set_property PULLTYPE $val $port
|
if {$io == "input"} continue
|
||||||
# puts "IOB $port $site $tile $pin $val"
|
|
||||||
puts $fp "$port,$site,$tile,$pin,$val"
|
set drive "4 8 12 16"
|
||||||
|
set drive_val [lindex $drive [expr {$idx % 4}]]
|
||||||
|
set_property DRIVE $drive_val $port
|
||||||
|
|
||||||
|
set slew "SLOW FAST"
|
||||||
|
set slew_val [lindex $slew [expr {($idx + ($idx / 4)) % 2}]]
|
||||||
|
set_property SLEW $slew_val $port
|
||||||
|
|
||||||
|
puts $fp "$port,$site,$tile,$pin,$iostandard_val,$slew_val,$drive_val,$pulltype_val"
|
||||||
}
|
}
|
||||||
close $fp
|
close $fp
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ all: build/env build/roi_roi_io.diff \
|
||||||
build/DRIVE/run.ok \
|
build/DRIVE/run.ok \
|
||||||
build/IOSTANDARD/run.ok \
|
build/IOSTANDARD/run.ok \
|
||||||
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
|
||||||
|
|
@ -35,3 +34,6 @@ build/DRIVE/run.ok:
|
||||||
build/IOSTANDARD/run.ok:
|
build/IOSTANDARD/run.ok:
|
||||||
PROJECT=IOSTANDARD bash runme_tcl.sh
|
PROJECT=IOSTANDARD bash runme_tcl.sh
|
||||||
|
|
||||||
|
csv:
|
||||||
|
PROJECT=$@ bash runme.sh
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# PULLTYPE
|
# PULLTYPE
|
||||||
|
|
||||||
PULLTYPE 28 29 30
|
PULLTYPE 38_98 39_97 39_97
|
||||||
NONE X
|
NONE X
|
||||||
KEEPER X X
|
KEEPER X X
|
||||||
PULLDOWN
|
PULLDOWN
|
||||||
|
|
@ -9,14 +9,31 @@ PULLUP X X
|
||||||
|
|
||||||
# DRIVE
|
# DRIVE
|
||||||
|
|
||||||
DRIVE A00 A02 A08 A10 B09 B01
|
Drive strength depends on current IOSTANDARD, e.g.
|
||||||
0 FIXME
|
|
||||||
|
LVCMOS18
|
||||||
|
DRIVE 38_64 38_66 38_72 38_74 39_65 39_73
|
||||||
4 X X X
|
4 X X X
|
||||||
8 X X X
|
8 X X X
|
||||||
12 X X X
|
12 X X X
|
||||||
16 X X X
|
16 X X X
|
||||||
24 FIXME
|
24 X X X
|
||||||
|
|
||||||
|
LVCMOS25
|
||||||
|
DRIVE 38_64 38_66 38_72 38_74 39_65 39_73
|
||||||
|
4 X X X
|
||||||
|
8 X
|
||||||
|
12
|
||||||
|
16 X X X
|
||||||
|
|
||||||
|
LVCMOS33
|
||||||
|
DRIVE 38_64 38_66 38_72 38_74 39_65 39_73
|
||||||
|
4 X X X
|
||||||
|
8 X X X
|
||||||
|
12 X X X
|
||||||
|
16 X X X
|
||||||
|
|
||||||
|
The minitest contains a csv target which generates a csv with differences across all LVCMOS and LVTTL standards for all supported DRIVE strengths and both slew rates.
|
||||||
|
|
||||||
# IOSTANDARD
|
# IOSTANDARD
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
import sys
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import difflib
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_pairs():
|
||||||
|
pairs_list = list()
|
||||||
|
for path1 in glob.glob('*.bits'):
|
||||||
|
for path2 in glob.glob('*.bits'):
|
||||||
|
file1 = os.path.basename(path1)
|
||||||
|
file2 = os.path.basename(path2)
|
||||||
|
if file1 == file2:
|
||||||
|
continue
|
||||||
|
files_pair = [file1, file2]
|
||||||
|
files_pair.sort()
|
||||||
|
pairs_list.append(files_pair[0] + ":" + files_pair[1])
|
||||||
|
pairs_set = set(pairs_list)
|
||||||
|
for pair in pairs_set:
|
||||||
|
file1, file2 = pair.split(":")
|
||||||
|
yield file1, file2
|
||||||
|
|
||||||
|
|
||||||
|
def extract_parameters_string(basename):
|
||||||
|
params_str = re.search('^design_(.*).bits$', basename)
|
||||||
|
return params_str.group(1)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_parameters(basename):
|
||||||
|
iostandard, slew, drive = extract_parameters_string(basename).split('_')
|
||||||
|
return iostandard, slew, drive
|
||||||
|
|
||||||
|
|
||||||
|
def generate_differing_bits(basename1, basename2):
|
||||||
|
with open(basename1, 'r') as path1:
|
||||||
|
with open(basename2, 'r') as path2:
|
||||||
|
diff = difflib.unified_diff(
|
||||||
|
path1.read().splitlines(),
|
||||||
|
path2.read().splitlines(),
|
||||||
|
fromfile='path1',
|
||||||
|
tofile='path2')
|
||||||
|
for line in diff:
|
||||||
|
if line.startswith('---'):
|
||||||
|
continue
|
||||||
|
if line.startswith('+++'):
|
||||||
|
continue
|
||||||
|
if line.startswith('@'):
|
||||||
|
continue
|
||||||
|
if line.startswith('-'):
|
||||||
|
yield extract_parameters_string(basename1), line.strip('-')
|
||||||
|
continue
|
||||||
|
if line.startswith('+'):
|
||||||
|
yield extract_parameters_string(basename2), line.strip('+')
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
class Database():
|
||||||
|
def __init__(self, convert_bits=False):
|
||||||
|
self.all_bits = set()
|
||||||
|
self.properties_bits = dict()
|
||||||
|
self.convert_bits = convert_bits
|
||||||
|
self.populate()
|
||||||
|
|
||||||
|
def populate(self):
|
||||||
|
for file1, file2 in get_file_pairs():
|
||||||
|
#print(file1 + " vs " + file2)
|
||||||
|
for property_str, bit in generate_differing_bits(file1, file2):
|
||||||
|
#print(property_str + " " + bit)
|
||||||
|
self.update_all_bits(bit)
|
||||||
|
if property_str in self.properties_bits:
|
||||||
|
self.properties_bits[property_str].add(bit)
|
||||||
|
else:
|
||||||
|
self.properties_bits[property_str] = set()
|
||||||
|
self.properties_bits[property_str].add(bit)
|
||||||
|
|
||||||
|
def update_all_bits(self, bit):
|
||||||
|
self.all_bits.add(bit)
|
||||||
|
|
||||||
|
def print_all_bits(self):
|
||||||
|
print(self.all_bits)
|
||||||
|
|
||||||
|
def get_keys(self):
|
||||||
|
return self.properties_bits.keys()
|
||||||
|
|
||||||
|
def print_bits(self, key):
|
||||||
|
if key in self.properties_bits:
|
||||||
|
print("%s: %s" % (key, self.properties_bits[key]))
|
||||||
|
else:
|
||||||
|
print("The specified property is not in the database")
|
||||||
|
|
||||||
|
def convert_bit_format(self, item):
|
||||||
|
dummy, address, word, bit = item.split("_")
|
||||||
|
address = int(address[-2:], 16)
|
||||||
|
bit = int(word) % 4 * 32 + int(bit)
|
||||||
|
return "{address}_{bit}".format(address=address, bit=bit)
|
||||||
|
|
||||||
|
def convert_header(self, header):
|
||||||
|
converted_bits = []
|
||||||
|
for bit in header:
|
||||||
|
#print(bit + ":" + self.convert_bit_format(bit))
|
||||||
|
converted_bits.append(self.convert_bit_format(bit))
|
||||||
|
return converted_bits
|
||||||
|
|
||||||
|
def get_csv_header(self):
|
||||||
|
header = list(self.all_bits)
|
||||||
|
header.sort()
|
||||||
|
self.csv_header = header
|
||||||
|
if self.convert_bits:
|
||||||
|
header = self.convert_header(header)
|
||||||
|
line = "property,v,i,r,"
|
||||||
|
for title in header:
|
||||||
|
line += title + ","
|
||||||
|
return line + '\n'
|
||||||
|
|
||||||
|
def extract_rvi_parameters(self, rvi):
|
||||||
|
iostandard, slew, drive = rvi.split("_")
|
||||||
|
if iostandard[-2:] == "12":
|
||||||
|
voltage = 1.2
|
||||||
|
elif iostandard[-2:] == "15":
|
||||||
|
voltage = 1.5
|
||||||
|
elif iostandard[-2:] == "18":
|
||||||
|
voltage = 1.8
|
||||||
|
elif iostandard[-2:] == "25":
|
||||||
|
voltage = 2.5
|
||||||
|
else:
|
||||||
|
voltage = 3.3
|
||||||
|
resistance = voltage / (int(drive) * 0.001)
|
||||||
|
return "%.1f,%s,%.3f" % (voltage, drive, resistance)
|
||||||
|
|
||||||
|
def get_csv_body(self):
|
||||||
|
lines = ""
|
||||||
|
keys = list(self.get_keys())
|
||||||
|
keys.sort()
|
||||||
|
for properties_key in keys:
|
||||||
|
line = properties_key + "," + self.extract_rvi_parameters(
|
||||||
|
properties_key) + ","
|
||||||
|
for title in self.csv_header:
|
||||||
|
if title in self.properties_bits[properties_key]:
|
||||||
|
line += "X,"
|
||||||
|
else:
|
||||||
|
line += " ,"
|
||||||
|
line += '\n'
|
||||||
|
lines += line
|
||||||
|
return lines
|
||||||
|
|
||||||
|
def write_csv(self, filename):
|
||||||
|
filename = os.getcwd() + "/" + filename
|
||||||
|
fp = open(filename, 'w')
|
||||||
|
fp.write(self.get_csv_header())
|
||||||
|
fp.write(self.get_csv_body())
|
||||||
|
fp.close()
|
||||||
|
print("Written results to %s file.\n" % filename)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
database = Database(True)
|
||||||
|
database.write_csv("differences.csv")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
source "$::env(XRAY_DIR)/utils/utils.tcl"
|
||||||
|
|
||||||
|
proc make_io_pin_sites {} {
|
||||||
|
# get all possible IOB pins
|
||||||
|
foreach pad [get_package_pins -filter "IS_GENERAL_PURPOSE == 1"] {
|
||||||
|
set site [get_sites -of_objects $pad]
|
||||||
|
if {[llength $site] == 0} {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if [string match IOB33* [get_property SITE_TYPE $site]] {
|
||||||
|
dict append io_pin_sites $site $pad
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $io_pin_sites
|
||||||
|
}
|
||||||
|
|
||||||
|
proc load_pin_lines {} {
|
||||||
|
# IOB_X0Y103 clk input
|
||||||
|
# IOB_X0Y129 do[0] output
|
||||||
|
|
||||||
|
set fp [open "$::env(SRC_DIR)/params.csv" r]
|
||||||
|
set pin_lines {}
|
||||||
|
for {gets $fp line} {$line != ""} {gets $fp line} {
|
||||||
|
lappend pin_lines [split $line ","]
|
||||||
|
}
|
||||||
|
close $fp
|
||||||
|
return $pin_lines
|
||||||
|
}
|
||||||
|
|
||||||
|
proc loc_pins {} {
|
||||||
|
set pin_lines [load_pin_lines]
|
||||||
|
set io_pin_sites [make_io_pin_sites]
|
||||||
|
|
||||||
|
puts "Looping"
|
||||||
|
foreach line $pin_lines {
|
||||||
|
puts "$line"
|
||||||
|
lassign $line site_str pin_str io cell_str
|
||||||
|
|
||||||
|
# Have: site
|
||||||
|
# Want: pin for site
|
||||||
|
set site [get_sites $site_str]
|
||||||
|
#set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
|
||||||
|
# set port [get_ports -of_objects $site]
|
||||||
|
set port [get_ports $pin_str]
|
||||||
|
set tile [get_tiles -of_objects $site]
|
||||||
|
set pin [dict get $io_pin_sites $site]
|
||||||
|
set iostandard [get_property IOSTANDARD $port]
|
||||||
|
|
||||||
|
set_property -dict "PACKAGE_PIN $pin IOSTANDARD $iostandard" $port
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc set_property_value_on_port {property value port} {
|
||||||
|
set_property $property $value $port
|
||||||
|
set got [get_property $property $port]
|
||||||
|
if {"$got" != "$value"} {
|
||||||
|
puts "Skipping: wanted $value, got $got"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
proc run {} {
|
||||||
|
create_project -force -part $::env(XRAY_PART) design design
|
||||||
|
read_verilog top.v
|
||||||
|
synth_design -top top
|
||||||
|
|
||||||
|
# Mostly doesn't matter since IOB are special, but add anyway
|
||||||
|
create_pblock roi
|
||||||
|
add_cells_to_pblock [get_pblocks roi] [get_cells roi]
|
||||||
|
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
|
||||||
|
|
||||||
|
set_property CFGBVS VCCO [current_design]
|
||||||
|
set_property CONFIG_VOLTAGE 3.3 [current_design]
|
||||||
|
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
|
||||||
|
set_param tcl.collectionResultDisplayLimit 0
|
||||||
|
|
||||||
|
loc_pins
|
||||||
|
place_design
|
||||||
|
route_design
|
||||||
|
set pin_lines [load_pin_lines]
|
||||||
|
# For HR Current Drive
|
||||||
|
set property_dictionary [dict create \
|
||||||
|
LVCMOS12 \
|
||||||
|
[dict create DRIVE [list 4 8 12] SLEW [list SLOW FAST]] \
|
||||||
|
LVCMOS15 \
|
||||||
|
[dict create DRIVE [list 4 8 12 16] SLEW [list SLOW FAST]] \
|
||||||
|
LVCMOS18 \
|
||||||
|
[dict create DRIVE [list 4 8 12 16 24] SLEW [list SLOW FAST]] \
|
||||||
|
LVCMOS25 \
|
||||||
|
[dict create DRIVE [list 4 8 12 16] SLEW [list SLOW FAST]] \
|
||||||
|
LVCMOS33 \
|
||||||
|
[dict create DRIVE [list 4 8 12 16] SLEW [list SLOW FAST]] \
|
||||||
|
LVTTL \
|
||||||
|
[dict create DRIVE [list 4 8 12 16 24] SLEW [list SLOW FAST]] \
|
||||||
|
]
|
||||||
|
#HSUL_12 no DRIVE support, only SLEW
|
||||||
|
#HSTL_I, HSTL_II, HSTL_I_18, HSTL_II_18 no drive support, only SLEW
|
||||||
|
#SSTL/18/135/ no drive support, only SLEW
|
||||||
|
|
||||||
|
foreach iostandard [dict keys $property_dictionary] {
|
||||||
|
foreach slew [dict get $property_dictionary $iostandard SLEW] {
|
||||||
|
foreach drive [dict get $property_dictionary $iostandard DRIVE] {
|
||||||
|
foreach line $pin_lines {
|
||||||
|
lassign $line site_str pin_str io cell_str
|
||||||
|
set port [get_ports $pin_str]
|
||||||
|
|
||||||
|
set_property IOSTANDARD $iostandard $port
|
||||||
|
|
||||||
|
if {$io == "input"} continue
|
||||||
|
|
||||||
|
if {[set_property_value_on_port SLEW $slew $port]} {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[set_property_value_on_port DRIVE $drive $port]} {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {[catch {write_bitstream -force design_${iostandard}_${slew}_${drive}.bit} issue]} {
|
||||||
|
puts "WARNING failed to write: $issue"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
# Only write checkpoints for acceptable bitstreams
|
||||||
|
write_checkpoint -force design_${iostandard}_${slew}_${drive}.dcp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
IOB_X0Y111,di[0],input,di_bufs[0].ibuf
|
||||||
|
IOB_X0Y107,do[0],output,do_bufs[0].obuf
|
||||||
|
|
|
@ -6,13 +6,14 @@ set -ex
|
||||||
|
|
||||||
# Create build dir
|
# Create build dir
|
||||||
export SRC_DIR=$PWD
|
export SRC_DIR=$PWD
|
||||||
BUILD_DIR=build/$PROJECT
|
export BUILD_DIR=build/$PROJECT
|
||||||
mkdir -p $BUILD_DIR
|
mkdir -p $BUILD_DIR
|
||||||
cd $BUILD_DIR
|
cd $BUILD_DIR
|
||||||
|
python3 ${SRC_DIR}/top.py > top.v
|
||||||
|
|
||||||
export TOP_V=$SRC_DIR/top.v
|
${XRAY_VIVADO} -mode batch -source $SRC_DIR/generate.tcl
|
||||||
|
for x in design*.bit; do
|
||||||
${XRAY_VIVADO} -mode batch -source $SRC_DIR/runme.tcl
|
${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o ${x}s -z -y $x
|
||||||
${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o design.bits -z -y design.bit
|
done
|
||||||
test -z "$(fgrep CRITICAL vivado.log)"
|
test -z "$(fgrep CRITICAL vivado.log)" && touch run.ok
|
||||||
|
python3 ${SRC_DIR}/compare.py
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,150 @@
|
||||||
|
'''
|
||||||
|
Generate a primitive to place at every I/O
|
||||||
|
Unlike CLB tests, the LFSR for this is inside the ROI, not driving it
|
||||||
|
'''
|
||||||
|
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import sys
|
||||||
|
#random.seed(int(os.getenv("SEED"), 16))
|
||||||
|
from prjxray import util
|
||||||
|
from prjxray import verilog
|
||||||
|
|
||||||
|
|
||||||
|
def gen_iobs():
|
||||||
|
'''
|
||||||
|
IOB33S: main IOB of a diff pair
|
||||||
|
IOB33M: secondary IOB of a diff pair
|
||||||
|
IOB33: not a diff pair. Relatively rare (at least in ROI...2 of them?)
|
||||||
|
Focus on IOB33S to start
|
||||||
|
'''
|
||||||
|
for _tile_name, site_name, site_type in util.get_roi().gen_sites(
|
||||||
|
#['IOB33', 'IOB33S', 'IOB33M']):
|
||||||
|
['IOB33S']):
|
||||||
|
yield site_name, site_type
|
||||||
|
|
||||||
|
|
||||||
|
def write_pins(ports):
|
||||||
|
pinstr = ''
|
||||||
|
for site, (name, dir_, cell) in sorted(ports.items(), key=lambda x: x[1]):
|
||||||
|
# pinstr += 'set_property -dict "PACKAGE_PIN %s IOSTANDARD LVCMOS33" [get_ports %s]' % (packpin, port)
|
||||||
|
pinstr += '%s,%s,%s,%s\n' % (site, name, dir_, cell)
|
||||||
|
open('params.csv', 'w').write(pinstr)
|
||||||
|
|
||||||
|
|
||||||
|
def run():
|
||||||
|
# All possible values
|
||||||
|
iosites = {}
|
||||||
|
for site_name, site_type in gen_iobs():
|
||||||
|
iosites[site_name] = site_type
|
||||||
|
|
||||||
|
# Assigned in this design
|
||||||
|
ports = {}
|
||||||
|
DIN_N = 0
|
||||||
|
DOUT_N = 0
|
||||||
|
|
||||||
|
def remain_sites():
|
||||||
|
return set(iosites.keys()) - set(ports.keys())
|
||||||
|
|
||||||
|
def rand_site():
|
||||||
|
'''Get a random, unused site'''
|
||||||
|
return random.choice(list(remain_sites()))
|
||||||
|
|
||||||
|
def get_site():
|
||||||
|
return next(iter(remain_sites()))
|
||||||
|
|
||||||
|
def assign_i(site, name):
|
||||||
|
nonlocal DIN_N
|
||||||
|
|
||||||
|
assert site not in ports
|
||||||
|
cell = "di_bufs[%u].ibuf" % DIN_N
|
||||||
|
DIN_N += 1
|
||||||
|
ports[site] = (name, 'input', cell)
|
||||||
|
|
||||||
|
def assign_o(site, name):
|
||||||
|
nonlocal DOUT_N
|
||||||
|
|
||||||
|
assert site not in ports
|
||||||
|
cell = "do_bufs[%u].obuf" % DOUT_N
|
||||||
|
DOUT_N += 1
|
||||||
|
ports[site] = (name, 'output', cell)
|
||||||
|
|
||||||
|
# Assign at least one di and one do
|
||||||
|
assign_i(get_site(), 'di[0]')
|
||||||
|
assign_o(get_site(), 'do[0]')
|
||||||
|
# Now assign the rest randomly
|
||||||
|
#while len(remain_sites()):
|
||||||
|
# assign_o(rand_site(), 'do[%u]' % DOUT_N)
|
||||||
|
|
||||||
|
#write_pins(ports)
|
||||||
|
|
||||||
|
print(
|
||||||
|
'''
|
||||||
|
`define N_DI %u
|
||||||
|
`define N_DO %u
|
||||||
|
|
||||||
|
module top(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do);
|
||||||
|
genvar i;
|
||||||
|
|
||||||
|
//Instantiate BUFs so we can LOC them
|
||||||
|
|
||||||
|
wire [`N_DI-1:0] di_buf;
|
||||||
|
generate
|
||||||
|
for (i = 0; i < `N_DI; i = i+1) begin:di_bufs
|
||||||
|
IBUF #(
|
||||||
|
) ibuf(.I(di[i]), .O(di_buf[i]));
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
wire [`N_DO-1:0] do_unbuf;
|
||||||
|
generate
|
||||||
|
for (i = 0; i < `N_DO; i = i+1) begin:do_bufs
|
||||||
|
OBUF #(
|
||||||
|
) obuf(.I(do_unbuf[i]), .O(do[i]));
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
roi roi(.di(di_buf), .do(do_unbuf));
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
//Arbitrary terminate into LUTs
|
||||||
|
module roi(input wire [`N_DI-1:0] di, output wire [`N_DO-1:0] do);
|
||||||
|
genvar i;
|
||||||
|
|
||||||
|
generate
|
||||||
|
for (i = 0; i < `N_DI; i = i+1) begin:dis
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
LUT6 #(
|
||||||
|
.INIT(64'h8000_0000_0000_0001)
|
||||||
|
) lut (
|
||||||
|
.I0(di[i]),
|
||||||
|
.I1(di[i]),
|
||||||
|
.I2(di[i]),
|
||||||
|
.I3(di[i]),
|
||||||
|
.I4(di[i]),
|
||||||
|
.I5(di[i]),
|
||||||
|
.O());
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
|
||||||
|
generate
|
||||||
|
for (i = 0; i < `N_DO; i = i+1) begin:dos
|
||||||
|
(* KEEP, DONT_TOUCH *)
|
||||||
|
LUT6 #(
|
||||||
|
.INIT(64'h8000_0000_0000_0001)
|
||||||
|
) lut (
|
||||||
|
.I0(),
|
||||||
|
.I1(),
|
||||||
|
.I2(),
|
||||||
|
.I3(),
|
||||||
|
.I4(),
|
||||||
|
.I5(),
|
||||||
|
.O(do[i]));
|
||||||
|
end
|
||||||
|
endgenerate
|
||||||
|
endmodule
|
||||||
|
''' % (DIN_N, DOUT_N))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
run()
|
||||||
|
|
@ -76,9 +76,6 @@ def run():
|
||||||
assign_o(rand_site(), 'do[0]')
|
assign_o(rand_site(), 'do[0]')
|
||||||
# Now assign the rest randomly
|
# Now assign the rest randomly
|
||||||
while len(remain_sites()):
|
while len(remain_sites()):
|
||||||
if random.randint(0, 1):
|
|
||||||
assign_i(rand_site(), 'di[%u]' % DIN_N)
|
|
||||||
else:
|
|
||||||
assign_o(rand_site(), 'do[%u]' % DOUT_N)
|
assign_o(rand_site(), 'do[%u]' % DOUT_N)
|
||||||
|
|
||||||
write_pins(ports)
|
write_pins(ports)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue