iob-pips: initial attempt to document ioi pips

Signed-off-by: Alessandro Comodi <acomodi@antmicro.com>
This commit is contained in:
Alessandro Comodi 2019-07-08 17:37:00 +02:00
parent b6b8dc19cd
commit e26a6432a4
9 changed files with 799 additions and 0 deletions

View File

@ -0,0 +1,48 @@
export FUZDIR=$(shell pwd)
PIP_TYPE?=ioi3
PIPLIST_TCL=$(FUZDIR)/ioi3_pip_list.tcl
TODO_RE="[LR]IOI3\.(IOI_([IO]LOGIC[01]_CLK(DIV|B)?)|(IOI_OCLK_[01]))\.IOI_LEAF_GCLK[0-9]"
MAKETODO_FLAGS=--pip-type ${PIP_TYPE} --seg-type $(PIP_TYPE) --re $(TODO_RE)
N = 40
SEGMATCH_FLAGS=-c 2 -m 15 -M 30
SPECIMENS_DEPS=build/cmt_regions.csv
include ../pip_loop.mk
build/segbits_ioi3_x.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} ${SEGMATCH_FLAGS} -o build/segbits_ioi3_x.rdb \
$(shell find build -name segdata_lioi3*.txt) $(shell find build -name segdata_rioi3*.txt)
RDBS = build/segbits_ioi3_x.rdb
database: ${RDBS}
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf \
--seg-fn-in build/segbits_ioi3_x.rdb \
--seg-fn-out build/segbits_ioi3_x.db
# Keep a copy to track iter progress
cp build/segbits_ioi3_x.rdb build/$(ITER)/segbits_ioi3_x.rdb
cp build/segbits_ioi3_x.db build/$(ITER)/segbits_ioi3_x.db
${XRAY_MASKMERGE} build/mask_xioi3.db \
$(shell find build -name segdata_ioi3_l.txt) \
$(shell find build -name segdata_ioi3_r.txt)
# Clobber existing .db to eliminate potential conflicts
cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} ioi3_l build/segbits_ioi3_x.db
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} ioi3_r build/segbits_ioi3_x.db
build/cmt_regions.csv: output_cmt.tcl
mkdir -p build
cd build/ && ${XRAY_VIVADO} -mode batch -source ${FUZDIR}/output_cmt.tcl
pushdb:
${XRAY_MERGEDB} lioi3 build/segbits_ioi3_x.db
${XRAY_MERGEDB} rioi3 build/segbits_ioi3_x.db
.PHONY: database pushdb

View File

View File

@ -0,0 +1,104 @@
#!/usr/bin/env python3
from prjxray.segmaker import Segmaker
import os, re
import os.path
def bitfilter(frame, word):
if frame < 26:
return False
return True
def main():
segmk = Segmaker("design.bits")
tiledata = {}
pipdata = {}
ignpip = set()
with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
'ioi3', 'ioi3_l.txt')) as f:
for l in f:
tile_type, dst, src = l.strip().split('.')
if tile_type not in pipdata:
pipdata[tile_type] = []
pipdata[tile_type].append((src, dst))
with open(os.path.join(os.getenv('FUZDIR'), '..', 'piplist', 'build',
'ioi3', 'ioi3_r.txt')) as f:
for l in f:
tile_type, dst, src = l.strip().split('.')
if tile_type not in pipdata:
pipdata[tile_type] = []
pipdata[tile_type].append((src, dst))
print("Loading tags from design.txt.")
with open("design.txt", "r") as f:
for line in f:
tile, pip, src, dst, pnum, pdir = line.split()
if not tile.startswith('LIOI3') and not tile.startswith('RIOI3'):
continue
log = open("log.txt", "a")
print(line, file=log)
pip_prefix, _ = pip.split(".")
tile_from_pip, tile_type = pip_prefix.split('/')
_, src = src.split("/")
_, dst = dst.split("/")
pnum = int(pnum)
pdir = int(pdir)
if tile not in tiledata:
tiledata[tile] = {
"type": tile_type,
"pips": set(),
"srcs": set(),
"dsts": set(),
}
tiledata[tile]["pips"].add((src, dst))
tiledata[tile]["srcs"].add(src)
tiledata[tile]["dsts"].add(dst)
if pdir == 0:
tiledata[tile]["srcs"].add(dst)
tiledata[tile]["dsts"].add(src)
if pnum == 1 or pdir == 0:
print("Ignoring pip: {}".format(pip), file=log)
ignpip.add((src, dst))
for tile, pips_srcs_dsts in tiledata.items():
tile_type = pips_srcs_dsts["type"]
if tile_type.startswith('LIOI3'):
tile_type = 'LIOI3'
elif tile_type.startswith('RIOI3'):
tile_type = 'RIOI3'
pips = pips_srcs_dsts["pips"]
for src, dst in pipdata[tile_type]:
if (src, dst) in ignpip:
pass
if re.match(r'.*PHASER.*', src) or re.match(r'.*CLKDIV[PFB].*',
dst):
pass
elif (src, dst) in tiledata[tile]["pips"]:
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 1)
elif (src, dst) not in tiledata[tile]["pips"]:
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0)
internal_feedback = False
segmk.compile(bitfilter=bitfilter)
segmk.write()
if __name__ == "__main__":
main()

View File

@ -0,0 +1,250 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc write_pip_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
set nets [get_nets -hierarchical]
set nnets [llength $nets]
set neti 0
foreach net $nets {
incr neti
if {($neti % 100) == 0 } {
puts "FUZ([pwd]): Dumping pips from net $net ($neti / $nnets)"
}
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
close $fp
}
proc load_todo {} {
set fp [open "../todo.txt" r]
# Create map of pip source to remaining destinations for that pip
set todo_map [dict create]
for {gets $fp line} {$line != ""} {gets $fp line} {
set parts [split $line .]
dict lappend todo_map [lindex $parts 1] [list [lindex $parts 0] [lindex $parts 2]]
}
close $fp
return $todo_map
}
proc route_todo {} {
puts "Checking TODO's"
set todo_map [load_todo]
puts $todo_map
set nets [get_nets]
set todo_nets [dict create]
set used_sources [dict create]
foreach net $nets {
# Check to see if this net is one we are interested in
set wires [get_wires -of_objects $net -filter {TILE_NAME =~ *IOI3*}]
set is_gclk_net 0
foreach wire $wires {
if [regexp "IOI_\[IO\]LOGIC\[01\]_CLKB?" $wire] {
set is_gclk_net 1
break
}
if [regexp "IOI_OCLK_\[01\]" $wire] {
set is_gclk_net 1
break
}
if [regexp "IOI_\[IO\]LOGIC\[01\]_CLKDIV" $wire] {
set is_gclk_net 1
break
}
}
if {$is_gclk_net == 0} {
puts "$net not going to a IOI3 port, skipping."
continue
}
foreach wire $wires {
set tile [lindex [split $wire /] 0]
set wire [lindex [split $wire /] 1]
set tile_type [get_property TILE_TYPE [get_tiles $tile]]
if { ![dict exists $todo_map $wire] } {
continue
}
set srcs [dict get $todo_map $wire]
# This net is interesting, see if it is already going somewhere we
# want.
set found_target 0
foreach other_wire $wires {
if { $found_target == 1 } {
break
}
set other_wire [lindex [split $other_wire /] 1]
if { $wire == $other_wire } {
continue
}
foreach src $srcs {
set src_tile_type [lindex $src 0]
if {$src_tile_type != $tile_type} {
continue
}
set src_wire [lindex $src 1]
if { $other_wire == $src } {
set found_target 1
puts "Interesting net $net already going from $wire to $other_wire."
break
}
}
}
if { $found_target == 1 } {
# Net has an interesting
continue
}
dict set todo_nets $net [list $tile $wire]
puts "Interesting net $net (including $wire) is being rerouted."
}
}
dict for {net tile_wire} $todo_nets {
set tile [lindex $tile_wire 0]
set wire [lindex $tile_wire 1]
set srcs [dict get $todo_map $wire]
set site [lindex [get_sites -of_objects [get_tiles $tile]] 0]
set region [get_clock_regions -of_objects [get_sites $site]]
puts "Rerouting net $net at $tile / $wire (type $tile_type)"
set tile_type [get_property TILE_TYPE [get_tiles $tile]]
set todos {}
foreach src $srcs {
set src_tile_type [lindex $src 0]
if {$src_tile_type != $tile_type} {
continue
}
set src_wire [lindex $src 1]
set is_gclk_net 0
if [regexp "IOI_LEAF_GCLK\[0-9\]+" $src_wire] {
set is_gclk_net 1
}
if {$is_gclk_net == 0} {
continue
}
lappend todos $src_wire
}
puts "All todos for $tile_type / $wire"
foreach src_wire $todos {
puts " - $src_wire"
}
route_design -unroute -nets $net
# Find an input in the todo list that this can can drive.
foreach src_wire $todos {
puts "Attempting to route to $src_wire for net $net."
set target_wire [get_wires "$tile/$src_wire"]
set target_node [get_nodes -of_objects $target_wire]
if {[llength $target_node] == 0} {
error "Failed to find node for $tile/$src_wire."
}
if { [regexp ".*TOP.*" $target_node match group] } {
set loc TOP
} elseif { [regexp ".*BOT.*" $target_node match group] } {
set loc BOT
}
if { [dict exists $used_sources "$region/$loc/$src_wire"] } {
puts "Not routing to $tile / $src_wire, in use."
continue
}
set old_nets [get_nets -of_objects $target_node]
if { $old_nets != {} } {
set old_nets_property [get_property IS_ROUTE_FIXED [get_nets -of_objects $target_node]]
if { $old_nets_property == 0 } {
route_design -unroute -nets $old_nets
}
}
set origin_node [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]]
set new_route [find_routing_path -to $target_node -from $origin_node]
puts "Origin node: $origin_node"
puts "Target wire: $target_wire"
puts "Target node: $target_node"
# Only need to set route to one of the destinations.
# Router will handle the rest.
set_property FIXED_ROUTE $new_route $net
dict set used_sources "$region/$loc/$src_wire" 1
break
}
}
}
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property IS_ENABLED 0 [get_drc_checks {PDRC-25}]
set_property IS_ENABLED 0 [get_drc_checks {PDRC-39}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-4}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-5}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-98}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-99}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-123}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-144}]
set_property IS_ENABLED 0 [get_drc_checks {REQP-1576}]
set_property IS_ENABLED 0 [get_drc_checks {AVAL-74}]
set_property IS_ENABLED 0 [get_drc_checks {AVAL-81}]
set_property IS_ENABLED 0 [get_drc_checks {DRC INBB-1}]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]
place_design
route_design
write_checkpoint -force design_before.dcp
route_todo
route_design
write_checkpoint -force design_after.dcp
set_property SEVERITY {Warning} [get_drc_checks UCIO-1]
set_property SEVERITY {Warning} [get_drc_checks NSTD-1]
write_bitstream -force design.bit
write_pip_txtdata design.txt
}
run

View File

@ -0,0 +1,43 @@
proc print_tile_pips {tile_type filename} {
set fp [open $filename w]
set pips [dict create]
foreach tile [get_tiles -filter "TYPE == $tile_type"] {
puts "Dumping PIPs for tile $tile ($tile_type) to $filename."
foreach pip [lsort [get_pips -of_objects $tile]] {
set src [get_wires -uphill -of_objects $pip]
set dst [get_wires -downhill -of_objects $pip]
# Skip pips with disconnected nodes
set src_node [get_nodes -of_objects $src]
if { $src_node == {} } {
continue
}
set dst_node [get_nodes -of_objects $src]
if { $dst_node == {} } {
continue
}
if {[llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] != 1} {
set pip_string "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]"
if ![dict exists $pips $pip_string] {
puts $fp $pip_string
dict set pips $pip_string 1
}
}
}
}
close $fp
}
create_project -force -part $::env(XRAY_PART) design design
set_property design_mode PinPlanning [current_fileset]
open_io_design -name io_1
# Cleaning ioi3.txt pip file
set fp [open ioi3.txt w]
close $fp
print_tile_pips LIOI3 ioi3_l.txt
print_tile_pips RIOI3 ioi3_r.txt

View File

@ -0,0 +1,11 @@
create_project -force -part $::env(XRAY_PART) design design
set_property design_mode PinPlanning [current_fileset]
open_io_design -name io_1
set fp [open "cmt_regions.csv" "w"]
foreach site_type {MMCME2_ADV BUFHCE BUFR BUFMRCE BUFIO ILOGICE3 OLOGICE3 IDELAYE2 IDELAYCTRL PLLE2_ADV} {
foreach site [get_sites -filter "SITE_TYPE == $site_type"] {
puts $fp "$site,[get_property CLOCK_REGION $site]"
}
}
close $fp

336
fuzzers/037-iob-pips/top.py Normal file
View File

@ -0,0 +1,336 @@
import json
import io
import os
import random
import math
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
NOT_INCLUDED_TILES = ['LIOI3_SING', 'RIOI3_SING']
SITE_TYPES = ['OLOGICE3', 'ILOGICE3']
REGIONAL_CLOCK_BUFFERS = ['BUFHCE', 'BUFIO']
GLOBAL_CLOCK_BUFFERS = ['BUFGCTRL']
CLOCK_BUFFERS = REGIONAL_CLOCK_BUFFERS + GLOBAL_CLOCK_BUFFERS
MAX_REG_CLK_BUF = 2
MAX_GLB_CLK_BUF = 24
CUR_CLK = 0
MAX_ATTEMPTS = 50
def get_location(tile_name, divisor):
y_location = int(tile_name.split("Y")[-1])
if math.floor(y_location / divisor) % 2 == 0:
# Location is on the bottom of the row/tile
return "BOT"
else:
return "TOP"
def read_site_to_cmt():
""" Yields clock sources and which CMT they route within. """
with open(os.path.join(os.getenv('FUZDIR'), 'build',
'cmt_regions.csv')) as f:
for l in f:
site, cmt = l.strip().split(',')
yield (site, cmt)
def gen_sites(site_types):
'''
Generates all sites belonging to `site_types` of
a desired `tile`
'''
db = Database(util.get_db_root())
grid = db.grid()
tiles = grid.tiles()
#Randomize tiles
tiles_list = list(tiles)
random.shuffle(tiles_list)
for tile_name in tiles:
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
tile_type = gridinfo.tile_type
for site_name, site_type in gridinfo.sites.items():
if site_type in site_types:
yield tile_type, tile_name, site_type, site_name
def generate_mmcm(site_to_cmt, clock_region):
mmcm_clocks = None
for _, _, _, site in gen_sites('MMCME2_ADV'):
mmcm_region = site_to_cmt[site]
if mmcm_region == clock_region:
mmcm_clocks = [
'mmcm_clock_{site}_{idx}'.format(site=site, idx=idx)
for idx in range(3)
]
print(
"""
wire {c0}, {c1}, {c2};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
MMCME2_ADV mmcm_{site} (
.CLKOUT0({c0}),
.CLKOUT1({c1}),
.CLKOUT2({c2})
);""".format(
site=site,
c0=mmcm_clocks[0],
c1=mmcm_clocks[1],
c2=mmcm_clocks[2]))
if not mmcm_clocks:
return None
return mmcm_clocks
def generate_glb_clk_buf(clock_regions, mmcm_clocks_dict):
clk_buf_count = 0
clock_signals = []
for tile_type, _, site_type, site_name in gen_sites(GLOBAL_CLOCK_BUFFERS):
if clk_buf_count >= MAX_GLB_CLK_BUF:
break
clock_signal = "buf_clk_{site}".format(site=site_name)
if site_type == 'BUFGCTRL':
mmcm_clocks = []
for clock_region in clock_regions:
# BUFGCTRL must have the clock coming from the same fabric row
if ('Y0' in clock_region and tile_type == 'CLK_BUFG_BOT_R'
) or ('Y0' not in clock_region
and tile_type == 'CLK_BUFG_TOP_R'):
mmcm_clocks = mmcm_clocks_dict[clock_region]
break
assert mmcm_clocks, "No clock can be produced. Buffer not instantiated"
print(
'''
wire {clk_out};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
BUFG buf_{site} (.I({clk_in}), .O({clk_out}));'''.format(
clk_in=random.choice(mmcm_clocks),
clk_out=clock_signal,
site=site_name))
else:
assert False, "The site is somehow corrupted"
clk_buf_count += 1
clock_signals.append(clock_signal)
return clock_signals
def generate_reg_clk_buf(site_to_cmt, clock_region, mmcm_clocks, buf_type):
clk_buf_count = 0
clock_signals = []
for tile_type, _, site_type, site_name in gen_sites(
REGIONAL_CLOCK_BUFFERS):
buf_region = site_to_cmt[site_name]
if clk_buf_count >= MAX_REG_CLK_BUF:
break
if buf_type != site_type:
continue
if buf_region != clock_region:
continue
clock_signal = "buf_clk_{site}".format(site=site_name)
if site_type == 'BUFR':
print(
'''
wire {clk_out};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
BUFR buf_{site} (.I({clk_in}), .O({clk_out}));'''.format(
clk_in=random.choice(mmcm_clocks),
clk_out=clock_signal,
site=site_name))
elif site_type == 'BUFIO':
print(
'''
wire {clk_out};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
BUFIO buf_{site} (.I({clk_in}), .O({clk_out}));'''.format(
clk_in=random.choice(mmcm_clocks),
clk_out=clock_signal,
site=site_name))
elif site_type == 'BUFHCE':
print(
'''
wire {clk_out};
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
BUFH buf_{site} (.I({clk_in}), .O({clk_out}));'''.format(
clk_in=random.choice(mmcm_clocks),
clk_out=clock_signal,
site=site_name))
else:
assert False, "The site is somehow corrupted"
clk_buf_count += 1
clock_signals.append(clock_signal)
return clock_signals
def get_clock_signal(clock_signals, clock_types):
'''
Get a unique clock signals for a specific tile.
'''
global CUR_CLK
clock_signal_string = ''
is_first_clock = True
for clock_type in clock_types:
if random.choice([True, True, False]):
continue
clock_signal = clock_signals[CUR_CLK]
if is_first_clock:
clock_signal_string += '''
.{}({})'''.format(clock_type, clock_signal)
else:
clock_signal_string += ''',
.{}({})'''.format(clock_type, clock_signal)
is_first_clock = False
CUR_CLK = (CUR_CLK + 1) % MAX_GLB_CLK_BUF
return clock_signal_string
def run():
global CUR_CLK
# One buffer type for each specimen
buf_type = random.choice(GLOBAL_CLOCK_BUFFERS)
site_location = random.choice(['TOP', 'BOT'])
site_to_cmt = dict(read_site_to_cmt())
clock_regions = list(dict.fromkeys(site_to_cmt.values()))
print("module top();")
clock_mmcm_dict = {}
clock_signals_dict = {}
site_types_dict = {}
# Generate MMCM Clock generator
for clock_region in clock_regions:
mmcm_clocks = generate_mmcm(site_to_cmt, clock_region)
if mmcm_clocks:
clock_mmcm_dict[clock_region] = mmcm_clocks
clock_signals_dict[clock_region] = []
if buf_type in REGIONAL_CLOCK_BUFFERS:
clock_signals_dict[clock_region] = generate_reg_clk_buf(
site_to_cmt, clock_region, mmcm_clocks, buf_type)
else:
clock_regions.remove(clock_region)
if buf_type in GLOBAL_CLOCK_BUFFERS:
clock_signals = generate_glb_clk_buf(clock_regions, clock_mmcm_dict)
for clock_region in clock_regions:
clock_signals_dict[clock_region] = clock_signals
site_types_dict[clock_region] = random.choice(SITE_TYPES)
half_column_used_clocks = {}
for tile_type, tile_name, site_type, site_name in gen_sites(SITE_TYPES):
if tile_type in NOT_INCLUDED_TILES:
continue
if random.choice([True, True, False]):
continue
site_region = site_to_cmt[site_name]
if site_type != site_types_dict[site_region]:
continue
clock_signals = clock_signals_dict[site_region]
bot_or_top = get_location(site_name, 1)
half_column = '{}_{}'.format(site_region, get_location(tile_name, 25))
if half_column not in half_column_used_clocks:
half_column_used_clocks[half_column] = {
'TOP': {
'ILOGIC':
get_clock_signal(clock_signals, ['CLK', 'CLKB', 'CLKDIV']),
'OLOGIC':
get_clock_signal(clock_signals, ['CLK', 'CLKDIV'])
},
'BOT': {
'ILOGIC':
get_clock_signal(clock_signals, ['CLK', 'CLKB', 'CLKDIV']),
'OLOGIC':
get_clock_signal(clock_signals, ['CLK', 'CLKDIV'])
}
}
if site_type == 'ILOGICE3':
print(
'''
(* KEEP, DONT_TOUCH, LOC = "{site_name}" *)
ISERDESE2 #(
.DATA_RATE("SDR")
) iserdes_{site_name} ({clk});'''.format(
site_name=site_name,
clk=half_column_used_clocks[half_column][bot_or_top]
['ILOGIC']))
elif site_type == 'OLOGICE3':
print(
'''
(* KEEP, DONT_TOUCH, LOC = "{site_name}" *)
OSERDESE2 #(
.DATA_RATE_OQ("SDR"),
.DATA_RATE_TQ("SDR")
) oserdes_{site_name} ({clk});'''.format(
site_name=site_name,
clk=half_column_used_clocks[half_column][bot_or_top]
['OLOGIC']))
print("endmodule")
if __name__ == '__main__':
run()

View File

@ -88,6 +88,7 @@ $(eval $(call fuzzer,034-cmt-pll-pips,005-tilegrid))
$(eval $(call fuzzer,035-iob-ilogic,005-tilegrid))
$(eval $(call fuzzer,035a-iob-idelay,005-tilegrid))
$(eval $(call fuzzer,036-iob-ologic,005-tilegrid))
$(eval $(call fuzzer,037-iob-pips,005-tilegrid))
$(eval $(call fuzzer,038-cfg,005-tilegrid))
$(eval $(call fuzzer,040-clk-hrow-config,005-tilegrid))
$(eval $(call fuzzer,041-clk-hrow-pips,005-tilegrid))

View File

@ -144,6 +144,12 @@ case "$1" in
hclk_ioi3)
cp "$2" "$tmp1" ;;
ioi3_l)
sed < "$2" > "$tmp1" -e 's/^IOI3\./LIOI3./' ;;
ioi3_r)
sed < "$2" > "$tmp1" -e 's/^IOI3\./RIOI3./' ;;
mask_*)
db=$XRAY_DATABASE_DIR/$XRAY_DATABASE/$1.db
ismask=true