Add 100-dsp-mskpat fuzzer

Signed-off-by: Clifford Wolf <clifford@clifford.at>
diff --git a/fuzzers/100-dsp-mskpat/.gitignore b/fuzzers/100-dsp-mskpat/.gitignore
new file mode 100644
index 0000000..4a41bd9
--- /dev/null
+++ b/fuzzers/100-dsp-mskpat/.gitignore
@@ -0,0 +1,3 @@
+/specimen_[0-9][0-9][0-9]/
+/seg_dsp_[lr].segbits
+/run.ok
diff --git a/fuzzers/100-dsp-mskpat/Makefile b/fuzzers/100-dsp-mskpat/Makefile
new file mode 100644
index 0000000..42c02da
--- /dev/null
+++ b/fuzzers/100-dsp-mskpat/Makefile
@@ -0,0 +1,29 @@
+
+N := 1
+SPECIMENS := $(addprefix specimen_,$(shell seq -f '%03.0f' $(N)))
+SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS))
+
+database: $(SPECIMENS_OK)
+	${XRAY_SEGMATCH} -o seg_dsp_l.segbits $(addsuffix /segdata_dsp_l_*.txt,$(SPECIMENS))
+	${XRAY_SEGMATCH} -o seg_dsp_r.segbits $(addsuffix /segdata_dsp_r_*.txt,$(SPECIMENS))
+
+pushdb:
+	${XRAY_MERGEDB} dsp_l seg_dsp_l.segbits
+	${XRAY_MERGEDB} dsp_r seg_dsp_r.segbits
+	${XRAY_DBFIXUP}
+
+$(SPECIMENS_OK):
+	bash generate.sh $(subst /OK,,$@)
+	touch $@
+
+run:
+	$(MAKE) clean
+	$(MAKE) database
+	$(MAKE) pushdb
+	touch run.ok
+
+clean:
+	rm -rf specimen_[0-9][0-9][0-9]/ seg_dsp_l.segbits seg_dsp_r.segbits run.ok
+
+.PHONY: database pushdb run clean
+
diff --git a/fuzzers/100-dsp-mskpat/generate.py b/fuzzers/100-dsp-mskpat/generate.py
new file mode 100644
index 0000000..989ade1
--- /dev/null
+++ b/fuzzers/100-dsp-mskpat/generate.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python3
+
+import sys, os, re
+
+sys.path.append("../../../utils/")
+from segmaker import segmaker
+
+segmk = segmaker("design_%s.bits" % sys.argv[1])
+
+pipdata = dict()
+ignpip = set()
+
+print("Loading tags from design.txt.")
+with open("design_%s.txt" % sys.argv[1], "r") as f:
+    for line in f:
+        tile, loc, mask, pattern = line.split()
+        dsp = "DSP_0" if loc[-1] in "02468" else "DSP_1"
+
+        mask = int(mask.replace("48'h", ""), 16)
+        pattern = int(pattern.replace("48'h", ""), 16)
+
+        for i in range(48):
+            segmk.addtag(tile, "%s.MASK[%d]" % (dsp, i), (mask >> i) & 1)
+            segmk.addtag(tile, "%s.PATTERN[%d]" % (dsp, i), (pattern >> i) & 1)
+
+segmk.compile()
+segmk.write(suffix=sys.argv[1])
diff --git a/fuzzers/100-dsp-mskpat/generate.sh b/fuzzers/100-dsp-mskpat/generate.sh
new file mode 100644
index 0000000..8ee7167
--- /dev/null
+++ b/fuzzers/100-dsp-mskpat/generate.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+source ${XRAY_GENHEADER}
+
+vivado -mode batch -source ../generate.tcl
+
+for i in {10..29}; do
+	${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o design_${i}.bits -z -y design_${i}.bit
+	python3 ../generate.py $i
+done
+
diff --git a/fuzzers/100-dsp-mskpat/generate.tcl b/fuzzers/100-dsp-mskpat/generate.tcl
new file mode 100644
index 0000000..fe98aa6
--- /dev/null
+++ b/fuzzers/100-dsp-mskpat/generate.tcl
@@ -0,0 +1,71 @@
+create_project -force -part $::env(XRAY_PART) design design
+
+read_verilog ../top.v
+synth_design -top top
+
+set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports i]
+set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports o]
+
+create_pblock 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
+
+place_design
+route_design
+
+write_checkpoint -force design.dcp
+
+source ../../../utils/utils.tcl
+set cells [list]
+
+set gnd_net [create_net gnd_net]
+set gnd_cell [create_cell -reference GND gnd_cell]
+connect_net -net $gnd_net -objects [get_pins $gnd_cell/G]
+
+foreach site [get_sites -of_objects [filter [roi_tiles] -filter {TYPE == "DSP_L" || TYPE == "DSP_R"}] -filter {SITE_TYPE =~ DSP*}] {
+	set cell [create_cell -reference DSP48E1 ${site}_cell]
+	lappend cells $cell
+	set_property LOC $site $cell
+	foreach pin [get_pins -of_objects $cell -filter {DIRECTION == "IN"}] {
+		connect_net -net $gnd_net -objects $pin
+	}
+}
+
+route_design
+
+proc write_txtdata {filename} {
+	upvar 1 cells cells
+	puts "Writing $filename."
+	set fp [open $filename w]
+	foreach cell $cells {
+		set loc [get_property LOC $cell]
+		set mask [get_property MASK $cell]
+		set pattern [get_property PATTERN $cell]
+		set tile [get_tiles -of_objects [get_sites -filter "NAME == $loc"]]
+		puts $fp "$tile $loc $mask $pattern"
+	}
+	close $fp
+}
+
+proc randhex {len} {
+	set s ""
+	for {set i 0} {$i < $len} {incr i} {
+		set s "$s[format %x [expr {int(rand()*16)}]]"
+	}
+	return $s
+}
+
+for {set i 10} {$i < 30} {incr i} {
+	foreach cell $cells {
+		set_property MASK "48'h[randhex 12]" $cell
+		set_property PATTERN "48'h[randhex 12]" $cell
+	}
+	write_checkpoint -force design_${i}.dcp
+	write_bitstream -force design_${i}.bit
+	write_txtdata design_${i}.txt
+}
+
diff --git a/fuzzers/100-dsp-mskpat/top.v b/fuzzers/100-dsp-mskpat/top.v
new file mode 100644
index 0000000..c0e91c5
--- /dev/null
+++ b/fuzzers/100-dsp-mskpat/top.v
@@ -0,0 +1,3 @@
+module top (input i, output o);
+	assign o = i;
+endmodule