diff --git a/fuzzers/034b-cmt-mmcm-pips/fixup_and_group.py b/fuzzers/034b-cmt-mmcm-pips/fixup_and_group.py index 10e1a008..49fff972 100755 --- a/fuzzers/034b-cmt-mmcm-pips/fixup_and_group.py +++ b/fuzzers/034b-cmt-mmcm-pips/fixup_and_group.py @@ -220,9 +220,6 @@ def main(): tags_to_remove = set() for tag, bits in segbits.items(): - if len(bits) == 0: - tags_to_remove.add(tag) - if 'REBUF' in tag and 'ACTIVE' not in tag: # FIXME: Removing REBUF pips for now. tags_to_remove.add(tag) @@ -232,15 +229,14 @@ def main(): for tag in segbits.keys(): if tag.endswith("_ACTIVE") and 'FREQ_BB' in tag: - if 'FREQ_BB_REBUF' in tag: - m = re.search('FREQ_BB_REBUF([0-9])', tag) - else: - m = re.search('FREQ_BB_NS([0-9])', tag) - assert m is not None, tag - - prefix = '.CMT_R_LOWER_B_CLK_FREQ_BB{}'.format(m.group(1)) - tags_to_mask = [t for t in segbits.keys() if t.endswith(prefix)] - mask_out_bits(segbits, segbits[tag], tags_to_mask) + for idx in range(4): + prefix1 = '.CMT_L_LOWER_B_CLK_FREQ_BB{}'.format(idx) + prefix2 = '.CMT_R_LOWER_B_CLK_FREQ_BB{}'.format(idx) + tags_to_mask = [ + t for t in segbits.keys() + if t.endswith(prefix1) or t.endswith(prefix2) + ] + mask_out_bits(segbits, segbits[tag], tags_to_mask) # Find common bits bit_groups = find_common_bits_for_tag_groups(segbits, tag_groups) diff --git a/fuzzers/034b-cmt-mmcm-pips/generate.tcl b/fuzzers/034b-cmt-mmcm-pips/generate.tcl index 2283ec1b..7491c08e 100644 --- a/fuzzers/034b-cmt-mmcm-pips/generate.tcl +++ b/fuzzers/034b-cmt-mmcm-pips/generate.tcl @@ -47,6 +47,116 @@ proc write_used_wires {filename} { close $fp } +proc load_route {line} { + puts "MANROUTE: Line: $line" + + # Parse the line + set fields [split $line " "] + set tile_name [lindex $fields 0] + set site_name [lindex $fields 1] + set pin_name [lindex $fields 2] + set route_dir [lindex $fields 3] + set wires [lrange $fields 4 end] + + # Get net + set tile [get_tiles $tile_name] + set site [get_sites -of_objects $tile $site_name] + set pin [get_site_pins -of_objects $site "*/$pin_name"] + set net [get_nets -quiet -of_objects $pin] + + if {$net eq "" } { + puts "MANROUTE: No net for pin $pin_name found! Skipping..." + return + } + + set source_pin [get_pins -of $net -filter "DIRECTION == OUT"] + if { [llength $source_pin] == 0 } { + error "Failed to find source pin of net $net" + } + + set source_site_pins [get_site_pins -of $source_pin] + puts "MANROUTE: Possible site pins for net $net: $source_site_pins" + + # Fixed part read from file + set route_list {} + if { [string first / $wires] != -1 } { + # Route list is just intermediate node and final node, fill it in + if { [llength $wires] != 2} { + error "Expected only 2 wires, found [llength $wires]" + } + + set intermediate_node [get_nodes [lindex $wires 0]] + set dest_node [get_nodes -of_objects [get_wires -of_objects $tile "*/[lindex $wires 1]"]] + if [catch {find_routing_path -from $intermediate_node -to $dest_node} route_list] { + puts "MANROUTE: Failed to find routing path from $intermediate_node to $dest_node for net $net\nError: $route_list" + return + } + + if { [llength $route_list] == 0 } { + puts "MANROUTE: Failed to find routing path from $intermediate_node to $dest_node for net $net" + return + } + } else { + foreach wire $wires { + lappend route_list [get_nodes -of_objects [get_wires -of_objects $tile "*/$wire"]] + } + } + + # Complete the route + if {$route_dir eq "up"} { + set node_to [lindex $route_list 0] + set node_from [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]] + + set rpart [find_routing_path -from $node_from -to $node_to] + if {$rpart eq ""} { + puts "MANROUTE: No possible route continuation for net $net" + return + } + + set route_list [concat [lrange $rpart 0 end-1] $route_list] + } + + if {$route_dir eq "down"} { + set node_from [lindex $route_list e] + set node_to [get_nodes -of_objects [get_site_pins -filter {DIRECTION == IN} -of_objects $net]] + + set rpart [find_routing_path -from $node_from -to $node_to] + if {$rpart eq ""} { + puts "MANROUTE: No possible route continuation for net $net" + return + } + set route_list [concat $route_list [lrange $rpart 1 end]] + } + + # Set the fixed route + puts "MANROUTE: Net: $net, Route: $route_list. routing..." + regsub -all {{}} $route_list "" route + if [catch {set_property FIXED_ROUTE $route $net} result] { + puts "MANROUTE: Net $net failed to set FIXED_ROUTE, ripping up...\nError: $result" + set_property FIXED_ROUTE "" $net + set_property IS_ROUTE_FIXED 0 $net + route_design -unroute -nets $net + } + + # Route the single net. Needed to detect conflicts when evaluating + # other ones + puts "Running route design" + route_design -quiet -directive Quick -nets $net + puts "Done running route design" + + # Check for conflicts. + set status [get_property ROUTE_STATUS $net] + if {$status ne "ROUTED"} { + # Ripup and discard the fixed route. + set_property FIXED_ROUTE "" $net + route_design -unroute -nets $net + puts "MANROUTE: Net $net status $status, ripping up..." + } else { + set_property IS_ROUTE_FIXED 1 $net + puts "MANROUTE: Successful manual route for $net" + } +} + proc load_routes {filename} { puts "MANROUTE: Loading routes from $filename" @@ -56,86 +166,7 @@ proc load_routes {filename} { continue } - puts "MANROUTE: Line: $line" - - # Parse the line - set fields [split $line " "] - set tile_name [lindex $fields 0] - set site_name [lindex $fields 1] - set pin_name [lindex $fields 2] - set route_dir [lindex $fields 3] - set wires [lrange $fields 4 end] - - # Get net - set tile [get_tiles $tile_name] - set site [get_sites -of_objects $tile $site_name] - set pin [get_site_pins -of_objects $site "*/$pin_name"] - set net [get_nets -quiet -of_objects $pin] - - if {$net eq "" } { - puts "MANROUTE: No net for pin $pin_name found! Skipping..." - continue - } - - # Fixed part read from file - set route_list {} - foreach wire $wires { - lappend route_list [get_nodes -of_objects [get_wires -of_objects $tile "*/$wire"]] - } - - # Complete the route - if {$route_dir eq "up"} { - set node_to [lindex $route_list 0] - set node_from [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]] - - set rpart [find_routing_path -from $node_from -to $node_to] - if {$rpart eq ""} { - puts "MANROUTE: No possible route continuation for net $net" - continue - } - - set route_list [concat [lrange $rpart 0 end-1] $route_list] - } - - if {$route_dir eq "down"} { - set node_from [lindex $route_list e] - set node_to [get_nodes -of_objects [get_site_pins -filter {DIRECTION == IN} -of_objects $net]] - - set rpart [find_routing_path -from $node_from -to $node_to] - if {$rpart eq ""} { - puts "MANROUTE: No possible route continuation for net $net" - continue - } - set route_list [concat $route_list [lrange $rpart 1 end]] - } - - # Set the fixed route - puts "MANROUTE: Net: $net, Route: $route_list. routing..." - regsub -all {{}} $route_list "" route - if [catch {set_property FIXED_ROUTE $route $net} ] { - puts "MANROUTE: Net $net failed to set FIXED_ROUTE, ripping up..." - set_property FIXED_ROUTE "" $net - set_property IS_ROUTE_FIXED 0 $net - route_design -unroute -nets $net - } - - # Route the single net. Needed to detect conflicts when evaluating - # other ones - puts "Running route design" - route_design -quiet -directive Quick -nets $net - puts "Done running route design" - - # Check for conflicts. - set status [get_property ROUTE_STATUS $net] - if {$status ne "ROUTED"} { - # Ripup and discard the fixed route. - set_property FIXED_ROUTE "" $net - route_design -unroute -nets $net - puts "MANROUTE: Net $net status $status, ripping up..." - } else { - set_property IS_ROUTE_FIXED 1 $net - puts "MANROUTE: Successful manual route for $net" - } + load_route $line } close $fp diff --git a/fuzzers/034b-cmt-mmcm-pips/tag_groups.txt b/fuzzers/034b-cmt-mmcm-pips/tag_groups.txt index e69de29b..2b088984 100644 --- a/fuzzers/034b-cmt-mmcm-pips/tag_groups.txt +++ b/fuzzers/034b-cmt-mmcm-pips/tag_groups.txt @@ -0,0 +1,11 @@ +CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_IN3_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_L_LOWER_B_CLK_IN3_INT + +CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_IN1_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_L_LOWER_B_CLK_IN1_INT + +CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_IN2_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_L_LOWER_B_CLK_IN2_INT + +CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_IN3_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKFBIN.CMT_R_LOWER_B_CLK_IN3_INT + +CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_IN1_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN1.CMT_R_LOWER_B_CLK_IN1_INT + +CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_FREQ_BB0 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_FREQ_BB1 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_FREQ_BB2 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_FREQ_BB3 CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_IN2_HCLK CMT_LOWER_B.CMT_LR_LOWER_B_MMCM_CLKIN2.CMT_R_LOWER_B_CLK_IN2_INT diff --git a/fuzzers/034b-cmt-mmcm-pips/top.py b/fuzzers/034b-cmt-mmcm-pips/top.py index 43b01dc5..5eb06ebb 100644 --- a/fuzzers/034b-cmt-mmcm-pips/top.py +++ b/fuzzers/034b-cmt-mmcm-pips/top.py @@ -84,6 +84,20 @@ def find_phasers_for_mmcm(grid, loc): return phasers +def find_hclk_ref_wires_for_mmcm(grid, loc): + tilename = grid.tilename_at_loc((loc[0], loc[1] - 17)) + gridinfo = grid.gridinfo_at_tilename(tilename) + + assert gridinfo.tile_type in ['HCLK_CMT_L', 'HCLK_CMT'] + + # HCLK_CMT_MUX_OUT_FREQ_REF[0-3] + wires = [] + for idx in range(4): + wires.append('{}/HCLK_CMT_MUX_OUT_FREQ_REF{}'.format(tilename, idx)) + + return wires + + def gen_sites(): db = Database(util.get_db_root(), util.get_part()) grid = db.grid() @@ -94,11 +108,12 @@ def gen_sites(): for site_name, site_type in gridinfo.sites.items(): if site_type in ['MMCME2_ADV']: phasers = find_phasers_for_mmcm(grid, loc) - yield tile_name, site_name, phasers + hclk_wires = find_hclk_ref_wires_for_mmcm(grid, loc) + yield tile_name, site_name, phasers, hclk_wires def get_random_route_from_site_pin( - pip_list, tile_name, site_pin, direction, occupied_wires): + pip_list, tile_name, site_pin, direction, occupied_wires, hclk_wires): # A map of MMCM site pins to wires they are connected to. pin_to_wire = { @@ -138,6 +153,9 @@ def get_random_route_from_site_pin( # The first wire wire = pin_to_wire[tile_type][site_pin] + if site_pin in ["CLKIN1", "CLKIN2", "CLKFBIN"] and random.random() < .2: + return [random.choice(hclk_wires), wire] + # Walk randomly. route = [] while True: @@ -199,7 +217,7 @@ module top( count = 0 mmcms = sorted(gen_sites(), key=lambda x: x[0]) random.shuffle(mmcms) - for tile, site, phasers in mmcms: + for tile, site, phasers, hclk_wires in mmcms: in_use = random.randint(0, 2) > 0 count += 1 @@ -219,20 +237,20 @@ module top( # Sometimes manually randomized route for CLKOUTx conflicts with # the verilog design. - ('CLKOUT0', 'down'), - ('CLKOUT1', 'down'), - ('CLKOUT2', 'down'), - ('CLKOUT3', 'down'), - ('CLKOUT4', 'down'), - ('CLKOUT5', 'down'), - ('CLKOUT6', 'down'), + #('CLKOUT0', 'down'), + #('CLKOUT1', 'down'), + #('CLKOUT2', 'down'), + #('CLKOUT3', 'down'), + #('CLKOUT4', 'down'), + #('CLKOUT5', 'down'), + #('CLKOUT6', 'down'), ] occupied_wires = set() for pin, dir in pins: route = get_random_route_from_site_pin( - pip_list, tile, pin, dir, occupied_wires) + pip_list, tile, pin, dir, occupied_wires, hclk_wires) if route is None: endpoints[pin] = "" continue @@ -248,11 +266,10 @@ module top( # Store them in a random order so the TCL script will try to route # them also in the random order. lines = [] - for pin, ( - route, - dir, - ) in routes.items(): - + pins = sorted(routes.keys()) + random.shuffle(pins) + for pin in pins: + (route, dir) = routes[pin] route_str = " ".join(route) lines.append( '{} {} {} {} {}\n'.format(tile, site, pin, dir, route_str))