diff --git a/fuzzers/034-iob-stag/Makefile b/fuzzers/034-iob-stag/Makefile new file mode 100644 index 00000000..1c2bc8da --- /dev/null +++ b/fuzzers/034-iob-stag/Makefile @@ -0,0 +1,20 @@ +N := 1 +include ../fuzzer.mk + +SEGDATAS=$(addsuffix /segdata_liob33.txt,$(SPECIMENS)) + +database: build/segbits_liob33.db + +build/segbits_liob33.rdb: $(SPECIMENS_OK) + ${XRAY_SEGMATCH} -c -1 -o build/segbits_liob33.rdb $(SEGDATAS) + +build/segbits_liob33.db: build/segbits_liob33.rdb + ${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@ + ${XRAY_MASKMERGE} build/mask_liob33.db $(SEGDATAS) + +pushdb: + ${XRAY_MERGEDB} liob33 build/segbits_liob33.db + ${XRAY_MERGEDB} mask_liob33 build/mask_liob33.db + +.PHONY: database pushdb + diff --git a/fuzzers/034-iob-stag/bits.dbf b/fuzzers/034-iob-stag/bits.dbf new file mode 100644 index 00000000..e69de29b diff --git a/fuzzers/034-iob-stag/generate.py b/fuzzers/034-iob-stag/generate.py new file mode 100644 index 00000000..3667d5a7 --- /dev/null +++ b/fuzzers/034-iob-stag/generate.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +from prjxray.segmaker import Segmaker +from prjxray import segmaker + +segmk = Segmaker("design.bits") + +print("Loading params") +f = open('params.csv', 'r') +f.readline() +for l in f: + l = l.strip() + site, name, dir_, cell = l.split(',') + segmaker.add_site_group_zero( + segmk, site, "MACRO.", ("INPUT", "OUTPUT"), "", dir_.upper()) + +segmk.compile() +segmk.write() diff --git a/fuzzers/034-iob-stag/generate.sh b/fuzzers/034-iob-stag/generate.sh new file mode 100644 index 00000000..f42f840c --- /dev/null +++ b/fuzzers/034-iob-stag/generate.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +set -ex +source ${XRAY_DIR}/utils/top_generate.sh + diff --git a/fuzzers/034-iob-stag/generate.tcl b/fuzzers/034-iob-stag/generate.tcl new file mode 100644 index 00000000..556d5814 --- /dev/null +++ b/fuzzers/034-iob-stag/generate.tcl @@ -0,0 +1,90 @@ +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 "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] + + set fp [open "design.csv" w] + puts $fp "port,site,tile,pin,val" + + puts "Looping" + for {set idx 1} {$idx < [llength $pin_lines]} {incr idx} { + set line [lindex $pin_lines $idx] + puts "$line" + + set site_str [lindex $line 0] + set pin_str [lindex $line 1] + set io [lindex $line 2] + set cell_str [lindex $line 3] + # Skip unused site + if {"$pin_str" == ""} { + continue + } + + # 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 $pin_str] + set tile [get_tiles -of_objects $site] + set pin [dict get $io_pin_sites $site] + + set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS33" $port + + puts $fp "$port,$site,$tile,$pin" + } + close $fp +} + +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)" + + loc_pins + + 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 + write_bitstream -force design.bit +} + +run diff --git a/fuzzers/034-iob-stag/top.py b/fuzzers/034-iob-stag/top.py new file mode 100644 index 00000000..8c2001f7 --- /dev/null +++ b/fuzzers/034-iob-stag/top.py @@ -0,0 +1,152 @@ +''' +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 +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 = 'site,name,dir,cell\n' + 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 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(rand_site(), 'di[0]') + assign_o(rand_site(), 'do[0]') + # Now assign the rest randomly + while len(remain_sites()): + site = rand_site() + choice = random.randint(0, 2) + if choice == 0: + assign_i(site, 'di[%u]' % DIN_N) + elif choice == 1: + assign_o(site, 'do[%u]' % DOUT_N) + # Empty to provide a reference for no instance + else: + ports[site] = ("", "", "") + + 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()