diff --git a/fuzzers/005-tilegrid/util.py b/fuzzers/005-tilegrid/util.py index 56e18ce5..468ba62a 100644 --- a/fuzzers/005-tilegrid/util.py +++ b/fuzzers/005-tilegrid/util.py @@ -105,7 +105,7 @@ def add_tile_bits( assert offset <= 100, (tile_name, offset) # Few rare cases at X=0 for double width tiles split in half => small negative offset - assert offset >= 0 or "IOB" in tile_name, ( + assert offset >= 0 or "IOB" in tile_name or "GTX_INT_INTERFACE" in tile_name, ( tile_name, hex(baseaddr), offset) assert 1 <= words <= 101, words assert offset + words <= 101, ( diff --git a/fuzzers/063-gtx-common-conf/Makefile b/fuzzers/063-gtx-common-conf/Makefile new file mode 100644 index 00000000..1b1d1d8a --- /dev/null +++ b/fuzzers/063-gtx-common-conf/Makefile @@ -0,0 +1,67 @@ +# 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 + +SHELL = bash + +N ?= 20 + +BUILD_DIR = build_${XRAY_PART} + +SPECIMENS := $(addprefix ${BUILD_DIR}/specimen_,$(shell seq -f '%03.0f' $(N))) +SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS)) +FUZDIR ?= ${PWD} + +CELLS_DATA_DIR = ${XRAY_FAMILY_DIR}/cells_data + +all: database + +# generate.sh / top_generate.sh call make, hence the command must +# have a + before it. +$(SPECIMENS_OK): $(SPECIMENS_DEPS) + mkdir -p ${BUILD_DIR} + bash ${XRAY_DIR}/utils/top_generate.sh $(subst /OK,,$@) + +run: + $(MAKE) clean + $(MAKE) database + $(MAKE) pushdb + touch run.${XRAY_PART}.ok + +clean: + rm -rf ${BUILD_DIR} run.${XRAY_PART}.ok + +.PHONY: all run clean + +# These are pins that are hard to parse as a regexp given that the port name ends with a number, which is misinterpreted +# as the index in the port bus +SPECIAL_PINS = PLLRSVD1,PLLRSVD2,GTREFCLK0,GTREFCLK1,GTGREFCLK0,GTGREFCLK1,GTEASTREFCLK0,GTEASTREFCLK1,GTWESTREFCLK0,GTWESTREFCLK1,REFCLKOUTMONITOR0,REFCLKOUTMONITOR1 + +$(BUILD_DIR)/gtxe2_common_ports.csv: generate_ports.tcl + env FILE_NAME=$(BUILD_DIR)/gtxe2_common_pins.csv ${XRAY_VIVADO} -mode batch -source generate_ports.tcl + +$(BUILD_DIR)/gtxe2_common_ports.json: $(BUILD_DIR)/gtxe2_common_ports.csv + python3 ${XRAY_UTILS_DIR}/make_ports.py $(BUILD_DIR)/gtxe2_common_pins.csv $(BUILD_DIR)/gtxe2_common_ports.json --special-pins $(SPECIAL_PINS) + +database: ${BUILD_DIR}/segbits_gtx_common.db $(BUILD_DIR)/gtxe2_common_ports.json + +${BUILD_DIR}/segbits_gtx_common.rdb: $(SPECIMENS_OK) + ${XRAY_SEGMATCH} -o ${BUILD_DIR}/segbits_gtx_common.rdb $$(find $(SPECIMENS) -name "segdata_gtx_common*") + +${BUILD_DIR}/segbits_gtx_common.db: ${BUILD_DIR}/segbits_gtx_common.rdb + ${XRAY_DBFIXUP} --db-root ${BUILD_DIR} --zero-db bits.dbf \ + --seg-fn-in ${BUILD_DIR}/segbits_gtx_common.rdb \ + --seg-fn-out ${BUILD_DIR}/segbits_gtx_common.db + ${XRAY_MASKMERGE} ${BUILD_DIR}/mask_gtx_common.db $$(find $(SPECIMENS) -name "segdata_gtx_common*") + +pushdb: + mkdir -p $(CELLS_DATA_DIR) + cp attrs.json $(CELLS_DATA_DIR)/gtxe2_common_attrs.json + cp $(BUILD_DIR)/gtxe2_common_ports.json $(CELLS_DATA_DIR)/gtxe2_common_ports.json + BUILD_DIR=$(BUILD_DIR) source pushdb.sh + +.PHONY: database pushdb diff --git a/fuzzers/063-gtx-common-conf/README.md b/fuzzers/063-gtx-common-conf/README.md new file mode 100644 index 00000000..a6526389 --- /dev/null +++ b/fuzzers/063-gtx-common-conf/README.md @@ -0,0 +1,33 @@ +GTXE2\_COMMON Primitive Configuration fuzzer +============================================ + +This fuzzer is used to document the parameters corresponding to the GTXE2\_COMMON primitive. + +It uses pre-built JSON containing a dictionary of parameters, each one with four attributes: + +- Type: one of Binary, Integer, String, Boolean. +- Values: all possible values that this parameter can assume. In case of `BIN` types, the values list contains only the maximum value reachable. +- Digits: number of digits (or bits) required to use a parameter. +- Encoding: This is present only for `INT` types of parameters. These reflect the actual encoding of the parameter value in the bit array. + +E.g.: + +```json +{ + "PLL0_REFCLK_DIV": { + "type": "INT", + "values": [1, 2], + "encoding": [16, 0], + "digits": 5 + } +} +``` + +In addition, there exist wires and PIPs that allow the connections of the `GTREFCLK` ports to clocks coming from the device fabric instead of the `IBUFDS_GTE2` primitive. + +In fact, if the clock comes from the device fabric, the physical `GTGREFCLK[01]` port is used instead of the `GTREFCLK[01]` one (even though the design's primitive port is always `GTREFCLK`). + +In the [User Guide (pg 27)](https://www.xilinx.com/support/documentation/user_guides/ug482_7Series_GTX_Transceivers.pdf), it is stated that the `GTGREFCLK[01]` port is used for "internal testing purposes". +Using this port is highly discouraged to get the reference clock from the fabric, as the recommended way is to get the clock from an external source using the `IBUFDS_GTE2` primitive. + +Therefore, in addition to the parameters, `IN_USE` and `ZINV\INV` features, this fuzzer documents also the `GTREFCLK[01]_USED` and `BOTH_GTREFCLK[01]_USED` features. diff --git a/fuzzers/063-gtx-common-conf/attrs.json b/fuzzers/063-gtx-common-conf/attrs.json new file mode 100644 index 00000000..bcb25e67 --- /dev/null +++ b/fuzzers/063-gtx-common-conf/attrs.json @@ -0,0 +1,83 @@ +{ + "QPLL_CFG": { + "type": "BIN", + "values": [134150145], + "digits": 27 + }, + "QPLL_CP": { + "type": "BIN", + "values": [1023], + "digits": 10 + }, + "QPLL_CP_MONITOR_EN": { + "type": "BIN", + "values": [1], + "digits": 1 + }, + "QPLL_DMONITOR_SEL": { + "type": "BIN", + "values": [1], + "digits": 1 + }, + "QPLL_REFCLK_DIV": { + "type": "INT", + "values": [1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20], + "encoding": [16, 0, 1, 2, 3, 5, 6, 7, 13, 14, 15], + "digits": 5 + }, + "QPLL_FBDIV": { + "type": "BIN", + "values": [496], + "digits": 10 + }, + "QPLL_FBDIV_MONITOR_EN": { + "type": "BIN", + "values": [1], + "digits": 1 + }, + "QPLL_FBDIV_RATIO": { + "type": "BIN", + "values": [1], + "digits": 1 + }, + "QPLL_LOCK_CFG": { + "type": "BIN", + "values": [65535], + "digits": 16 + }, + "QPLL_INIT_CFG": { + "type": "BIN", + "values": [16777215], + "digits": 24 + }, + "QPLL_LPF": { + "type": "BIN", + "values": [15], + "digits": 4 + }, + "COMMON_CFG": { + "type": "BIN", + "values": [4294836225], + "digits": 32 + }, + "QPLL_CLKOUT_CFG": { + "type": "BIN", + "values": [15], + "digits": 4 + }, + "QPLL_COARSE_FREQ_OVRD": { + "type": "BIN", + "values": [63], + "digits": 5 + }, + "QPLL_COARSE_FREQ_OVRD_EN": { + "type": "BIN", + "values": [1], + "digits": 1 + }, + "BIAS_CFG": { + "type": "BIN", + "values": [18445618199572250625], + "digits": 64 + } +} \ No newline at end of file diff --git a/fuzzers/063-gtx-common-conf/bits.dbf b/fuzzers/063-gtx-common-conf/bits.dbf new file mode 100644 index 00000000..e69de29b diff --git a/fuzzers/063-gtx-common-conf/generate.py b/fuzzers/063-gtx-common-conf/generate.py new file mode 100644 index 00000000..fed2e2b3 --- /dev/null +++ b/fuzzers/063-gtx-common-conf/generate.py @@ -0,0 +1,149 @@ +#!/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 os +from enum import Enum + +from prjxray.segmaker import Segmaker +#from icecream import ic + +INT = "INT" +BIN = "BIN" + + +def bitfilter_gtx_common_mid(frame, bit): + # Filter out non interesting bits. + word = int(bit / 32) + + if word < 44 or word > 56: + return False + + return True + + +def bitfilter_gtx_common(frame, bit): + # Filter out non interesting bits. + word = int(bit / 32) + + if word < 44 or word > 56: + return False + + return True + + +def main(): + segmk = Segmaker("design.bits") + + fuz_dir = os.getenv("FUZDIR", None) + assert fuz_dir + with open(os.path.join(fuz_dir, "attrs.json"), "r") as attr_file: + attrs = json.load(attr_file) + + print("Loading tags") + with open("params.json") as f: + params_dict = json.load(f) + tile_type = params_dict["tile_type"] + params_list = params_dict["params"] + + sites_in_tile = dict() + + for params in params_list: + site = params["site"] + tile = params["tile"] + + if "GTXE2_COMMON" not in site: + continue + + sites_in_tile[tile] = site + + in_use = params["IN_USE"] + + segmk.add_site_tag(site, "IN_USE", in_use) + + if in_use: + for param, param_info in attrs.items(): + value = params[param] + param_type = param_info["type"] + param_digits = param_info["digits"] + param_values = param_info["values"] + + if param_type == INT: + param_encodings = param_info["encoding"] + param_encoding = param_encodings[param_values.index(value)] + bitstr = [ + int(x) for x in "{value:0{digits}b}".format( + value=param_encoding, digits=param_digits)[::-1] + ] + + for i in range(param_digits): + segmk.add_site_tag( + site, '%s[%u]' % (param, i), bitstr[i]) + else: + assert param_type == BIN + bitstr = [ + int(x) for x in "{value:0{digits}b}".format( + value=value, digits=param_digits)[::-1] + ] + + for i in range(param_digits): + segmk.add_site_tag( + site, "%s[%u]" % (param, i), bitstr[i]) + + for param in ["QPLLLOCKDETCLK", "DRPCLK"]: + segmk.add_site_tag(site, "INV_" + param, params[param]) + + for param in ["GTREFCLK0_USED", "GTREFCLK1_USED", + "BOTH_GTREFCLK_USED"]: + segmk.add_site_tag(site, param, params[param]) + + segmk.add_site_tag(site, "ENABLE_DRP", params["ENABLE_DRP"]) + + for params in params_list: + site = params["site"] + + if "IBUFDS_GTE2" not in site: + continue + + in_use = params["IN_USE"] + segmk.add_site_tag(site, "IN_USE", in_use) + + if in_use: + tile = params["tile"] + + for param in ["CLKRCV_TRST", "CLKCM_CFG"]: + value = params[param] + segmk.add_site_tag(site, param, "TRUE" in value) + + bitstr = [ + int(x) for x in "{value:0{digits}b}".format( + value=params["CLKSWING_CFG"], digits=2)[::-1] + ] + + gtx_common_site = sites_in_tile[tile] + for i in range(2): + segmk.add_site_tag( + gtx_common_site, "IBUFDS_GTE2.CLKSWING_CFG[%u]" % (i), + bitstr[i]) + + if tile_type.startswith("GTX_COMMON_MID"): + bitfilter = bitfilter_gtx_common_mid + elif tile_type == "GTX_COMMON": + bitfilter = bitfilter_gtx_common + else: + assert False, tile_type + + segmk.compile(bitfilter=bitfilter) + segmk.write() + + +if __name__ == '__main__': + main() diff --git a/fuzzers/063-gtx-common-conf/generate.tcl b/fuzzers/063-gtx-common-conf/generate.tcl new file mode 100644 index 00000000..c720ac57 --- /dev/null +++ b/fuzzers/063-gtx-common-conf/generate.tcl @@ -0,0 +1,31 @@ +# 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 +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 {NSTD-1}] + set_property IS_ENABLED 0 [get_drc_checks {UCIO-1}] + set_property IS_ENABLED 0 [get_drc_checks {REQP-48}] + set_property IS_ENABLED 0 [get_drc_checks {REQP-47}] + set_property IS_ENABLED 0 [get_drc_checks {REQP-51}] + set_property IS_ENABLED 0 [get_drc_checks {REQP-1619}] + + place_design + route_design + + write_checkpoint -force design.dcp + write_bitstream -force design.bit +} + +run diff --git a/fuzzers/063-gtx-common-conf/generate_ports.tcl b/fuzzers/063-gtx-common-conf/generate_ports.tcl new file mode 100644 index 00000000..77d91ed7 --- /dev/null +++ b/fuzzers/063-gtx-common-conf/generate_ports.tcl @@ -0,0 +1,15 @@ +# 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 + +source "$::env(XRAY_DIR)/utils/utils.tcl" + +create_project -force -name design -part $::env(XRAY_PART) +set_property design_mode PinPlanning [current_fileset] +open_io_design -name io_1 + +dump_pins $::env(FILE_NAME) GTXE2_COMMON diff --git a/fuzzers/063-gtx-common-conf/pushdb.sh b/fuzzers/063-gtx-common-conf/pushdb.sh new file mode 100644 index 00000000..f7720612 --- /dev/null +++ b/fuzzers/063-gtx-common-conf/pushdb.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# 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 + +if ! test $(find ${BUILD_DIR} -name "segdata_gtx_common_mid_right.txt" | wc -c) -eq 0 +then + ${XRAY_MERGEDB} gtx_common_mid_right ${BUILD_DIR}/segbits_gtx_common.db + ${XRAY_MERGEDB} mask_gtx_common_mid_right ${BUILD_DIR}/mask_gtx_common.db + ${XRAY_MERGEDB} gtx_common_mid_left ${BUILD_DIR}/segbits_gtx_common.db + ${XRAY_MERGEDB} mask_gtx_common_mid_left ${BUILD_DIR}/mask_gtx_common.db +fi + +if ! test $(find ${BUILD_DIR} -name "segdata_gtx_common.txt" | wc -c) -eq 0 +then + ${XRAY_MERGEDB} gtx_common ${BUILD_DIR}/segbits_gtx_common.db + ${XRAY_MERGEDB} mask_gtx_common ${BUILD_DIR}/mask_gtx_common.db +fi diff --git a/fuzzers/063-gtx-common-conf/top.py b/fuzzers/063-gtx-common-conf/top.py new file mode 100644 index 00000000..21bd7496 --- /dev/null +++ b/fuzzers/063-gtx-common-conf/top.py @@ -0,0 +1,258 @@ +#!/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 os +import random +from collections import namedtuple + +random.seed(int(os.getenv("SEED"), 16)) +from prjxray import util +from prjxray import verilog +from prjxray.lut_maker import LutMaker +from prjxray.db import Database + +INT = "INT" +BIN = "BIN" + + +def gen_sites(tile, site, filter_cmt=None): + 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) + + if tile not in gridinfo.tile_type: + continue + else: + tile_type = gridinfo.tile_type + + for site_name, site_type in gridinfo.sites.items(): + if site_type != site: + continue + + cmt = gridinfo.clock_region + + if filter_cmt is not None and cmt != filter_cmt: + continue + + yield tile_name, tile_type, site_name, cmt + + +def main(): + print( + ''' +module top( + input wire in, + output wire out +); + +assign out = in; +''') + + luts = LutMaker() + + params_dict = {"tile_type": None} + params_list = list() + + clkswing_cfg_tiles = dict() + ibufds_out_wires = dict() + for tile_name, _, site_name, _ in gen_sites("GTX_COMMON", "IBUFDS_GTE2"): + # Both the IBUFDS_GTE2 in the same tile need to have + # the same CLKSWING_CFG parameter + if tile_name not in clkswing_cfg_tiles: + clkswing_cfg = random.randint(0, 3) + clkswing_cfg_tiles[tile_name] = clkswing_cfg + else: + clkswing_cfg = clkswing_cfg_tiles[tile_name] + + in_use = bool(random.randint(0, 9)) + params = { + "site": + site_name, + "tile": + tile_name, + "IN_USE": + in_use, + "CLKRCV_TRST": + verilog.quote("TRUE" if random.randint(0, 1) else "FALSE"), + "CLKCM_CFG": + verilog.quote("TRUE" if random.randint(0, 1) else "FALSE"), + "CLKSWING_CFG": + clkswing_cfg, + } + + if in_use: + ibufds_out_wire = "{}_O".format(site_name) + + if tile_name not in ibufds_out_wires: + ibufds_out_wires[tile_name] = list() + + ibufds_out_wires[tile_name].append( + (ibufds_out_wire, int(site_name[-1]) % 2)) + + print("wire {};".format(ibufds_out_wire)) + print("(* KEEP, DONT_TOUCH, LOC=\"{}\" *)".format(site_name)) + print( + """ +IBUFDS_GTE2 #( + .CLKRCV_TRST({CLKRCV_TRST}), + .CLKCM_CFG({CLKCM_CFG}), + .CLKSWING_CFG({CLKSWING_CFG}) +) {site} ( + .O({out}) +);""".format(**params, out=ibufds_out_wire)) + + params_list.append(params) + + DRP_PORTS = [ + ("DRPCLK", "clk"), ("DRPEN", "in"), ("DRPWE", "in"), ("DRPRDY", "out") + ] + + for tile_name, tile_type, site_name, cmt in gen_sites("GTX_COMMON", + "GTXE2_COMMON"): + + params_dict["tile_type"] = tile_type + + params = dict() + params['site'] = site_name + params['tile'] = tile_name + + verilog_attr = "" + + verilog_attr = "#(" + + fuz_dir = os.getenv("FUZDIR", None) + assert fuz_dir + with open(os.path.join(fuz_dir, "attrs.json"), "r") as attrs_file: + attrs = json.load(attrs_file) + + in_use = bool(random.randint(0, 9)) + params["IN_USE"] = in_use + + if in_use: + for param, param_info in attrs.items(): + param_type = param_info["type"] + param_values = param_info["values"] + param_digits = param_info["digits"] + + if param_type == INT: + value = random.choice(param_values) + value_str = value + else: + assert param_type == BIN + value = random.randint(0, param_values[0]) + value_str = "{digits}'b{value:0{digits}b}".format( + value=value, digits=param_digits) + + params[param] = value + + verilog_attr += """ + .{}({}),""".format(param, value_str) + + verilog_ports = "" + + for param in ["QPLLLOCKDETCLK", "DRPCLK"]: + is_inverted = random.randint(0, 1) + + params[param] = is_inverted + + verilog_attr += """ + .IS_{}_INVERTED({}),""".format(param, is_inverted) + verilog_ports += """ + .{}({}),""".format(param, luts.get_next_output_net()) + + verilog_attr = verilog_attr.rstrip(",") + verilog_attr += "\n)" + + for param in ["GTREFCLK0_USED", "GTREFCLK1_USED", + "BOTH_GTREFCLK_USED"]: + params[param] = 0 + + if tile_name in ibufds_out_wires: + gtrefclk_ports_used = 0 + + for wire, location in ibufds_out_wires[tile_name]: + if random.random() < 0.5: + continue + + verilog_ports += """ + .GTREFCLK{}({}),""".format(location, wire) + + gtrefclk_ports_used += 1 + params["GTREFCLK{}_USED".format(location)] = 1 + + if gtrefclk_ports_used == 2: + params["BOTH_GTREFCLK_USED"] = 1 + + enable_drp = random.randint(0, 1) + params["ENABLE_DRP"] = enable_drp + + for _, _, channel_site_name, _ in gen_sites("GTX_CHANNEL", + "GTXE2_CHANNEL", cmt): + + if not enable_drp: + break + + verilog_ports_channel = "" + for port, direction in DRP_PORTS: + if direction == "in": + verilog_ports_channel += """ + .{}({}),""".format(port, luts.get_next_output_net()) + + elif direction == "clk": + # DRPCLK needs to come from a clock source + print( + """ +wire clk_bufg_{site}; + +(* KEEP, DONT_TOUCH *) +BUFG bufg_{site} (.O(clk_bufg_{site}));""".format(site=channel_site_name)) + + verilog_ports_channel += """ + .{}(clk_bufg_{}),""".format(port, channel_site_name) + + elif direction == "out": + verilog_ports_channel += """ + .{}({}),""".format(port, luts.get_next_input_net()) + + print( + """ +(* KEEP, DONT_TOUCH, LOC=\"{site}\" *) +GTXE2_CHANNEL {site} ( + {ports} +);""".format(ports=verilog_ports_channel.rstrip(","), site=channel_site_name)) + + print( + """ +(* KEEP, DONT_TOUCH, LOC=\"{site}\" *) +GTXE2_COMMON {attrs} {site} ( + {ports} +);""".format( + attrs=verilog_attr, + ports=verilog_ports.rstrip(","), + site=site_name)) + + params_list.append(params) + + for l in luts.create_wires_and_luts(): + print(l) + + print("endmodule") + + params_dict["params"] = params_list + with open('params.json', 'w') as f: + json.dump(params_dict, f, indent=2) + + +if __name__ == '__main__': + main() diff --git a/fuzzers/Makefile b/fuzzers/Makefile index 9874db60..15b807f1 100644 --- a/fuzzers/Makefile +++ b/fuzzers/Makefile @@ -191,6 +191,9 @@ $(eval $(call fuzzer,065-gtp-common-pips,005-tilegrid,part)) $(eval $(call fuzzer,065b-gtp-common-pips,005-tilegrid,part)) $(eval $(call fuzzer,066-gtp-int-pips,005-tilegrid,all)) endif +ifeq ($(XRAY_DATABASE),kintex7) +$(eval $(call fuzzer,063-gtx-common-conf,005-tilegrid,part)) +endif endif endif $(eval $(call fuzzer,100-dsp-mskpat,005-tilegrid,all))