From b1780e76a07c4f4847e522e7b354b12e5ea2ce8b Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Fri, 19 Jul 2019 16:53:12 -0700 Subject: [PATCH] Refactor 037 to capture non-inverted pips. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- fuzzers/000-init-db/Makefile | 2 + fuzzers/037-iob-pips/Makefile | 2 +- fuzzers/037-iob-pips/generate.py | 4 +- fuzzers/037-iob-pips/generate.tcl | 17 +- fuzzers/037-iob-pips/top.py | 461 ++++++++++++++---------------- 5 files changed, 226 insertions(+), 260 deletions(-) diff --git a/fuzzers/000-init-db/Makefile b/fuzzers/000-init-db/Makefile index ebef99a1..f2c368d5 100644 --- a/fuzzers/000-init-db/Makefile +++ b/fuzzers/000-init-db/Makefile @@ -22,6 +22,8 @@ SEGBITS=\ dsp \ hclk \ int \ + ioi \ + ioi3 \ SEGBITS_R=\ clk_bufg_top \ diff --git a/fuzzers/037-iob-pips/Makefile b/fuzzers/037-iob-pips/Makefile index f31f236a..e77c23b4 100644 --- a/fuzzers/037-iob-pips/Makefile +++ b/fuzzers/037-iob-pips/Makefile @@ -7,7 +7,7 @@ TODO_RE="[LR]IOI3\.(IOI_([IO]LOGIC[01]_CLK(DIV|B)?)|(IOI_OCLK_[01]))\.IOI_LEAF_G MAKETODO_FLAGS=--pip-type ${PIP_TYPE} --seg-type $(PIP_TYPE) --re $(TODO_RE) N = 40 -SEGMATCH_FLAGS=-c 2 -m 15 -M 30 +SEGMATCH_FLAGS=-c -1 -m 15 -M 30 SPECIMENS_DEPS=build/cmt_regions.csv include ../pip_loop.mk diff --git a/fuzzers/037-iob-pips/generate.py b/fuzzers/037-iob-pips/generate.py index 5ea9eb91..bfc426ac 100644 --- a/fuzzers/037-iob-pips/generate.py +++ b/fuzzers/037-iob-pips/generate.py @@ -6,7 +6,7 @@ import os.path def bitfilter(frame, word): - if frame < 26: + if frame < 28: return False return True @@ -91,7 +91,7 @@ def main(): 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"]: + elif dst not in tiledata[tile]["dsts"]: segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0) internal_feedback = False diff --git a/fuzzers/037-iob-pips/generate.tcl b/fuzzers/037-iob-pips/generate.tcl index 8b81bcbe..a2d15ddf 100644 --- a/fuzzers/037-iob-pips/generate.tcl +++ b/fuzzers/037-iob-pips/generate.tcl @@ -217,32 +217,27 @@ proc run {} { 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 {AVAL-74}] + set_property IS_ENABLED 0 [get_drc_checks {PDRC-26}] 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-13}] 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-115}] 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 + write_checkpoint -force design_before_route.dcp route_design write_checkpoint -force design_before.dcp - route_todo + #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 } diff --git a/fuzzers/037-iob-pips/top.py b/fuzzers/037-iob-pips/top.py index e5fc72ef..e240db93 100644 --- a/fuzzers/037-iob-pips/top.py +++ b/fuzzers/037-iob-pips/top.py @@ -1,22 +1,16 @@ -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 import lut_maker 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 @@ -42,292 +36,267 @@ def read_site_to_cmt(): yield (site, cmt) -def gen_sites(site_types): - ''' - Generates all sites belonging to `site_types` of - a desired `tile` - ''' +def gen_sites(): + ''' Return dict of ISERDES/OSERDES locations. ''' db = Database(util.get_db_root()) grid = db.grid() + xy_fun = util.create_xy_fun('\S+') + tiles = grid.tiles() - #Randomize tiles - tiles_list = list(tiles) - random.shuffle(tiles_list) - - for tile_name in tiles: + for tile_name in sorted(tiles): loc = grid.loc_of_tilename(tile_name) gridinfo = grid.gridinfo_at_loc(loc) tile_type = gridinfo.tile_type + tile = { + 'tile': tile_name, + 'tile_type': tile_type, + 'ioi_sites': {} + } + for site_name, site_type in gridinfo.sites.items(): - if site_type in site_types: - yield tile_type, tile_name, site_type, site_name + if site_type in SITE_TYPES: + xy = xy_fun(site_name) + if xy not in tile['ioi_sites']: + tile['ioi_sites'][xy] = {} + + tile['ioi_sites'][xy][site_type] = site_name + + yield tile -def generate_mmcm(site_to_cmt, clock_region): - mmcm_clocks = None +class ClockSources(object): + def __init__(self): + self.site_to_cmt = dict(read_site_to_cmt()) - for _, _, _, site in gen_sites('MMCME2_ADV'): - mmcm_region = site_to_cmt[site] + self.leaf_gclks = {} + self.ioclks = {} + self.rclks = {} + self.selected_leaf_gclks = {} + self.lut_maker = lut_maker.LutMaker() - if mmcm_region == clock_region: - mmcm_clocks = [ - 'mmcm_clock_{site}_{idx}'.format(site=site, idx=idx) - for idx in range(3) - ] + for cmt in set(self.site_to_cmt.values()): + self.leaf_gclks[cmt] = [] + self.ioclks[cmt] = [] + self.rclks[cmt] = [] - print( - """ - wire {c0}, {c1}, {c2}; - (* KEEP, DONT_TOUCH, LOC = "{site}" *) - MMCME2_ADV mmcm_{site} ( - .CLKOUT0({c0}), - .CLKOUT1({c1}), - .CLKOUT2({c2}) - );""".format( + def init_clocks(self): + """ Initialize all IOI clock sources. """ + for site, cmt in self.site_to_cmt.items(): + clk = 'clk_' + site + if 'BUFHCE' in site: + print(""" + wire {clk}; + (* KEEP, DONT_TOUCH, LOC = "{site}" *) + BUFH bufh_{site}( + .O({clk}) + ); + """.format( + clk=clk, site=site, - c0=mmcm_clocks[0], - c1=mmcm_clocks[1], - c2=mmcm_clocks[2])) + )) - if not mmcm_clocks: - return None + self.leaf_gclks[cmt].append(clk) - return mmcm_clocks + if 'BUFIO' in site: + print(""" + wire {clk}; + (* KEEP, DONT_TOUCH, LOC = "{site}" *) + BUFIO bufio_{site}( + .O({clk}) + ); + """.format( + clk=clk, + site=site, + )) + + self.ioclks[cmt].append(clk) + + if 'BUFR' in site: + print(""" + wire {clk}; + (* KEEP, DONT_TOUCH, LOC = "{site}" *) + BUFR bufr_{site}( + .O({clk}) + ); + """.format( + clk=clk, + site=site, + )) + + self.rclks[cmt].append(clk) -def generate_glb_clk_buf(clock_regions, mmcm_clocks_dict): - clk_buf_count = 0 + # Choose 6 leaf_gclks to be used in each CMT. + for cmt in self.leaf_gclks: + self.selected_leaf_gclks[cmt] = random.choices(self.leaf_gclks[cmt], k=6) - clock_signals = [] + def get_clock(self, site, allow_ioclks, allow_rclks, allow_fabric=True, allow_empty=True): + cmt = self.site_to_cmt[site] + choices = [] + if allow_fabric: + choices.append('lut') - for tile_type, _, site_type, site_name in gen_sites(GLOBAL_CLOCK_BUFFERS): + if allow_empty: + choices.append('') - if clk_buf_count >= MAX_GLB_CLK_BUF: - break + choices.extend(self.selected_leaf_gclks[cmt]) + if allow_ioclks: + choices.extend(self.ioclks[cmt]) - clock_signal = "buf_clk_{site}".format(site=site_name) + if allow_rclks: + choices.extend(self.rclks[cmt]) - 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 + clock = random.choice(choices) + is_lut = False + if clock == "lut": + clock = self.lut_maker.get_next_output_net() + is_lut = True + return clock, is_lut -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 add_port(ports, port, signal): + ports.append('.{}({})'.format(port, signal)) 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 = {} + clocks = ClockSources() + clocks.init_clocks() - # 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] = [] + ISERDESE2 clock sources: - 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) + CLK/CLKB: + - Allows LEAF_GCLK, IOCLKS, RCLKS and fabric + - Dedicated pips - if buf_type in GLOBAL_CLOCK_BUFFERS: - clock_signals = generate_glb_clk_buf(clock_regions, clock_mmcm_dict) + CLKDIV: + - No dedicated pips, uses fabric clock in. - for clock_region in clock_regions: - clock_signals_dict[clock_region] = clock_signals - site_types_dict[clock_region] = random.choice(SITE_TYPES) + CLKDIVP: + - Has pips, MIG only, PHASER or fabric. - half_column_used_clocks = {} + OCLK/OCLKB: + - Allows LEAF_GCLK, IOCLKS, RCLKS and fabric + - Must match OSERDESE2:CLK/CLKB - for tile_type, tile_name, site_type, site_name in gen_sites(SITE_TYPES): - if tile_type in NOT_INCLUDED_TILES: + OSERDESE2 clock sources: + + CLKDIV/CLKDIVB: + - Allows LEAF_GCLK and RCLKS and fabric + - Dedicated pips + + CLKDIVF/CLKDIVFB: + - Allows LEAF_GCLK and RCLKS and fabric + - No explicit port, follows CLKDIV/CLKDIVB? + """ + + output = [] + + for tile in gen_sites(): + if tile['tile_type'] in NOT_INCLUDED_TILES: continue - if random.choice([True, True, False]): - continue - site_region = site_to_cmt[site_name] + for xy in tile['ioi_sites']: + use_iserdes = random.randint(0, 1) + use_oserdes = random.randint(0, 1) - if site_type != site_types_dict[site_region]: - continue + ilogic_site = tile['ioi_sites'][xy]['ILOGICE3'] + ologic_site = tile['ioi_sites'][xy]['OLOGICE3'] - clock_signals = clock_signals_dict[site_region] + if use_oserdes: + oclk, _ = clocks.get_clock( + ologic_site, + allow_ioclks=True, + allow_rclks=True) - bot_or_top = get_location(site_name, 1) + oclkb = oclk + else: + oclk, is_lut = clocks.get_clock( + ilogic_site, + allow_ioclks=True, + allow_rclks=True) - half_column = '{}_{}'.format(site_region, get_location(tile_name, 25)) + if random.randint(0, 1): + oclkb = oclk + else: + oclkb, _ = clocks.get_clock( + ilogic_site, + allow_ioclks=True, + allow_rclks=True, + allow_fabric=not is_lut) - 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 use_iserdes: + DATA_RATE = random.choice(['DDR', 'SDR']) + ports = [] - 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'])) + clk, is_lut = clocks.get_clock( + ilogic_site, + allow_ioclks=True, + allow_rclks=True, + allow_empty=DATA_RATE=='SDR') + if random.randint(0, 1): + clkb = clk + else: + clkb, _ = clocks.get_clock( + ilogic_site, + allow_ioclks=True, + allow_rclks=True, + allow_empty=DATA_RATE=='SDR') + + add_port(ports, 'CLK', clk) + add_port(ports, 'CLKB', clkb) + add_port(ports, 'OCLK', oclk) + add_port(ports, 'OCLKB', oclkb) + + output.append(""" + (* KEEP, DONT_TOUCH, LOC="{site}" *) + ISERDESE2 #( + .DATA_RATE({DATA_RATE}), + .INTERFACE_TYPE("MEMORY_QDR"), + .IS_CLK_INVERTED({IS_CLK_INVERTED}), + .IS_CLKB_INVERTED({IS_CLKB_INVERTED}) + ) iserdes_{site}( + {ports});""".format( + site=ilogic_site, + ports=',\n'.join(ports), + DATA_RATE=verilog.quote(DATA_RATE), + IS_CLK_INVERTED=random.randint(0, 1), + IS_CLKB_INVERTED=random.randint(0, 1), + )) + + if use_oserdes: + ports = [] + + add_port(ports, 'CLKDIV', clocks.get_clock( + ologic_site, + allow_ioclks=False, + allow_rclks=True, + )[0]) + + add_port(ports, 'CLK', oclk) + + output.append(""" + (* KEEP, DONT_TOUCH, LOC = "{site}" *) + OSERDESE2 #( + .DATA_RATE_OQ("SDR"), + .DATA_RATE_TQ("SDR") + ) oserdes_{site} ( + {ports});""".format( + site=ologic_site, + ports=',\n'.join(ports), + )) + + for s in clocks.lut_maker.create_wires_and_luts(): + print(s) + + for s in output: + print(s) print("endmodule")