diff --git a/database/artix7/settings.sh b/database/artix7/settings.sh index f7c335e0..a01e3c43 100644 --- a/database/artix7/settings.sh +++ b/database/artix7/settings.sh @@ -2,10 +2,13 @@ export XRAY_DATABASE="artix7" export XRAY_PART="xc7a50tfgg484-1" export XRAY_ROI_FRAMES="0x00000000:0xffffffff" -# Leave some CLBs to the left to allow easy ROI entering -export XRAY_ROI="SLICE_X8Y100:SLICE_X27Y149 RAMB18_X0Y40:RAMB18_X0Y59 RAMB36_X0Y20:RAMB36_X0Y29 DSP48_X0Y40:DSP48_X0Y59" -export XRAY_ROI_GRID_X1="18" -export XRAY_ROI_GRID_X2="47" +# All CLB's in part, all BRAM's in part, all DSP's in part. +export XRAY_ROI="SLICE_X0Y0:SLICE_X65Y99 SLICE_X0Y100:SLICE_X57Y149 RAMB18_X0Y0:RAMB18_X1Y59 RAMB36_X0Y0:RAMB36_X1Y29 RAMB18_X2Y0:RAMB18_X2Y39 RAMB36_X2Y0:RAMB36_X2Y19 DSP48_X0Y0:DSP48_X1Y59" + +# ROI is all of CMT X0Y2. +export XRAY_ROI_GRID_X1="10" +export XRAY_ROI_GRID_X2="58" +# Y = 0 and Y 52 are VBRK rows, include them export XRAY_ROI_GRID_Y1="0" export XRAY_ROI_GRID_Y2="52" diff --git a/fuzzers/005-tilegrid/Makefile b/fuzzers/005-tilegrid/Makefile index 0399ce20..c2801373 100644 --- a/fuzzers/005-tilegrid/Makefile +++ b/fuzzers/005-tilegrid/Makefile @@ -3,7 +3,7 @@ database: build/tilegrid.json pushdb: cp build/tilegrid.json ${XRAY_DATABASE_DIR}/$(XRAY_DATABASE)/tilegrid.json -build/tilegrid.json: build/deltas +build/tilegrid.json: build/deltas generate.py cd build && python3 ../generate.py design_*.delta > tilegrid.json build/deltas: diff --git a/fuzzers/005-tilegrid/generate.py b/fuzzers/005-tilegrid/generate.py index 77ab5a50..bfddd12e 100644 --- a/fuzzers/005-tilegrid/generate.py +++ b/fuzzers/005-tilegrid/generate.py @@ -145,6 +145,23 @@ def make_tiles_by_grid(tiles): return tiles_by_grid +def add_segment( + database, segments, name, tiles, segtype, verbose, baseaddr=None): + assert name not in segments + segment = segments.setdefault(name, {}) + segment["tiles"] = tiles + segment["type"] = segtype + if baseaddr: + verbose and print('make_segment: %s baseaddr %s' % ( + name, + baseaddr, + )) + segment["baseaddr"] = baseaddr + + for tile_name in tiles: + database[tile_name]["segment"] = name + + def make_segments(database, tiles_by_grid, tile_baseaddrs, verbose=False): ''' Create segments data structure @@ -163,22 +180,6 @@ def make_segments(database, tiles_by_grid, tile_baseaddrs, verbose=False): grid_x = tile_data["grid_x"] grid_y = tile_data["grid_y"] - def add_segment(name, tiles, segtype, baseaddr=None): - assert name not in segments - segment = segments.setdefault(name, {}) - segment["tiles"] = tiles - segment["type"] = segtype - if baseaddr: - verbose and print( - 'make_segment: %s baseaddr %s' % ( - name, - baseaddr, - )) - segment["baseaddr"] = baseaddr - - for tile_name in tiles: - database[tile_name]["segment"] = name - def process_clb(): if tile_type in ["CLBLL_L", "CLBLM_L"]: int_tile_name = tiles_by_grid[(grid_x + 1, grid_y)] @@ -186,16 +187,24 @@ def make_segments(database, tiles_by_grid, tile_baseaddrs, verbose=False): int_tile_name = tiles_by_grid[(grid_x - 1, grid_y)] add_segment( + database=database, + segments=segments, name="SEG_" + tile_name, tiles=[tile_name, int_tile_name], segtype=tile_type.lower(), - baseaddr=tile_baseaddrs.get(tile_name, None)) + baseaddr=tile_baseaddrs.get(tile_name, None), + verbose=verbose, + ) def process_hclk(): add_segment( + database=database, + segments=segments, name="SEG_" + tile_name, tiles=[tile_name], - segtype=tile_type.lower()) + segtype=tile_type.lower(), + verbose=verbose, + ) def process_bram_dsp(): for k in range(5): @@ -222,12 +231,16 @@ def make_segments(database, tiles_by_grid, tile_baseaddrs, verbose=False): baseaddr = None add_segment( + database=database, + segments=segments, # BRAM_L_X6Y70 => SEG_BRAM4_L_X6Y70 name="SEG_" + tile_name.replace("_", "%d_" % k, 1), tiles=tiles, # BRAM_L => bram4_l segtype=tile_type.lower().replace("_", "%d_" % k, 1), - baseaddr=baseaddr) + baseaddr=baseaddr, + verbose=verbose, + ) def process_default(): #verbose and nolr(tile_type) not in ('VBRK', 'INT', 'NULL') and print('make_segment: drop %s' % (tile_type,)) @@ -263,6 +276,39 @@ def get_bramtile(database, segment): return inttiles[0] +def create_segment_for_int_lr( + database, segments, tile, tiles_by_grid, verbose): + """ Creates INT_[LR] segment for interconnect's without direct connectivity. """ + # Some INT_[LR] tiles have no adjacent connectivity, create a segment. + grid_x = database[tile]["grid_x"] + grid_y = database[tile]["grid_y"] + if database[tile]["type"] == "INT_L": + grid_x -= 1 + adjacent_tile = tiles_by_grid[(grid_x, grid_y)] + elif database[tile]["type"] == "INT_R": + grid_x += 1 + adjacent_tile = tiles_by_grid[(grid_x, grid_y)] + else: + assert False, database[tile]["type"] + + if (database[adjacent_tile]['type'].startswith('INT_INTERFACE_') or + database[adjacent_tile]['type'].startswith('PCIE_INT_INTERFACE_') + or + database[adjacent_tile]['type'].startswith('GTP_INT_INTERFACE')): + # This INT_[LR] tile has no adjacent connectivity, + # create a segment. + add_segment( + database=database, + segments=segments, + name='SEG_' + tile, + tiles=[tile], + segtype=database[tile]["type"], + verbose=verbose, + ) + else: + assert False, database[adjacent_tile]['type'] + + def seg_base_addr_lr_INT(database, segments, tiles_by_grid, verbose=False): '''Populate segment base addresses: L/R along INT column''' ''' @@ -312,7 +358,11 @@ def seg_base_addr_lr_INT(database, segments, tiles_by_grid, verbose=False): else: assert 0 - assert "segment" in database[tile] + if 'segment' not in database[tile]: + if database[tile]['type'] in ['T_TERM_INT']: + continue + create_segment_for_int_lr( + database, segments, tile, tiles_by_grid, verbose) seg = database[tile]["segment"] @@ -366,6 +416,9 @@ def seg_base_addr_up_INT(database, segments, tiles_by_grid, verbose=False): for i in range(50): grid_y -= 1 + if grid_y < 0: + break + dst_tile = database[tiles_by_grid[(grid_x, grid_y)]] if wordbase == 50: @@ -373,6 +426,14 @@ def seg_base_addr_up_INT(database, segments, tiles_by_grid, verbose=False): else: wordbase += 2 + if 'segment' not in dst_tile: + if dst_tile['type'] in ['T_TERM_INT']: + continue + create_segment_for_int_lr( + database, segments, tiles_by_grid[(grid_x, + grid_y)], + tiles_by_grid, verbose) + #verbose and print(' dst_tile', dst_tile) dst_segment_name = dst_tile["segment"] #verbose and print('up_INT: %s => %s' % (src_segment_name, dst_segment_name)) @@ -417,6 +478,9 @@ def seg_base_addr_up_INT(database, segments, tiles_by_grid, verbose=False): grid_y -= 1 wordbase += 1 + if (grid_x, grid_y) not in tiles_by_grid: + continue + dst_tile = database[tiles_by_grid[(grid_x, grid_y)]] assert nolr(dst_tile['type']) == 'BRAM', dst_tile diff --git a/fuzzers/005-tilegrid/generate.tcl b/fuzzers/005-tilegrid/generate.tcl index 50410b84..abc903b1 100644 --- a/fuzzers/005-tilegrid/generate.tcl +++ b/fuzzers/005-tilegrid/generate.tcl @@ -11,7 +11,10 @@ proc make_project {} { create_pblock roi add_cells_to_pblock [get_pblocks roi] [get_cells roi] - resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)" + foreach roi "$::env(XRAY_ROI)" { + puts $roi + resize_pblock [get_pblocks roi] -add "$roi" + } set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] @@ -27,20 +30,39 @@ proc loc_luts {} { set lut_index 0 # LOC one LUT (a "selected_lut") into each CLB segment configuration column (ie 50 per CMT column) + set lut_columns "" foreach lut $luts { - set tile [get_tile -of_objects $lut] - set grid_x [get_property GRID_POINT_X $tile] - set grid_y [get_property GRID_POINT_Y $tile] + regexp "SLICE_X([0-9]+)Y([0-9]+)/" $lut match slice_x slice_y + + # Only even SLICEs should be used as column bases. + if { $slice_x % 2 != 0 } { + continue + } # 50 per column => 50, 100, 150, etc # ex: SLICE_X2Y50/A6LUT # Only take one of the CLBs within a slice - if [regexp "X.*[02468]Y.*[05]0/" $lut] { - set cell [get_cells roi/luts[$lut_index].lut] - set_property LOC [get_sites -of_objects $lut] $cell - set lut_index [expr $lut_index + 1] - lappend selected_luts $lut + set y_column [expr ($slice_y / 50) * 50] + dict append lut_columns "X${slice_x}Y${y_column}" "$lut " + } + + # Pick the smallest Y in each column. + dict for {column luts_in_column} $lut_columns { + set min_slice_y 9999999 + + foreach lut $luts_in_column { + regexp "SLICE_X([0-9]+)Y([0-9]+)/" $lut slice_x slice_y + + if { $slice_y < $min_slice_y } { + set selected_lut $lut + } } + + puts $selected_lut + set cell [get_cells roi/luts[$lut_index].lut] + set_property LOC [get_sites -of_objects [get_bels $selected_lut]] $cell + set lut_index [expr $lut_index + 1] + lappend selected_luts [get_bels $selected_lut] } return $selected_luts } @@ -53,20 +75,38 @@ proc loc_brams {} { set bram_index 0 # LOC one BRAM (a "selected_lut") into each BRAM segment configuration column (ie 10 per CMT column) + set bram_columns "" foreach bram $brams { - set tile [get_tile -of_objects $bram] - set grid_x [get_property GRID_POINT_X $tile] - set grid_y [get_property GRID_POINT_Y $tile] + regexp "RAMB36_X([0-9]+)Y([0-9]+)/" $bram match slice_x slice_y # 10 per column => 10, 20, ,etc # ex: RAMB36_X0Y10/RAMBFIFO36E1 - if [regexp "Y.*0/" $bram] { - set cell [get_cells roi/brams[$bram_index].bram] - set_property LOC [get_sites -of_objects $bram] $cell - set bram_index [expr $bram_index + 1] - lappend selected_brams $bram - } + set y_column [expr ($slice_y / 10) * 10] + dict append lut_columns "X${slice_x}Y${y_column}" "$bram " } + + # Pick the smallest Y in each column. + dict for {column brams_in_column} $lut_columns { + set min_slice_y 9999999 + + foreach bram $brams_in_column { + regexp "RAMB36_X([0-9]+)Y([0-9]+)/" $bram match slice_x slice_y + + if { $slice_y < $min_slice_y } { + set selected_bram $bram + } + } + + puts "" + puts $selected_bram + + set cell [get_cells roi/brams[$bram_index].bram] + set_property LOC [get_sites -of_objects [get_bels $selected_bram]] $cell + puts $selected_bram + set bram_index [expr $bram_index + 1] + lappend selected_brams [get_bels $selected_bram] + } + return $selected_brams } @@ -132,7 +172,7 @@ proc run {} { set selected_luts [loc_luts] puts "Selected LUTs: [llength $selected_luts]" set selected_brams [loc_brams] - puts "Selected LUTs: [llength $selected_brams]" + puts "Selected BRAMs: [llength $selected_brams]" place_design route_design diff --git a/minitests/roi_harness/Makefile b/minitests/roi_harness/Makefile index 9c03896b..7d564867 100644 --- a/minitests/roi_harness/Makefile +++ b/minitests/roi_harness/Makefile @@ -1,16 +1,24 @@ BUILD_DIR=build +HARNESS_DIR ?= harness export BUILD_DIR XRAY_PINCFG ?= BASYS3-SWBUT export XRAY_PINCFG +HARNESS_FILES=$(BUILD_DIR)/design.bit $(BUILD_DIR)/design.txt $(BUILD_DIR)/design.json $(BUILD_DIR)/design.dcp + # official demo configuration -all: +all: $(HARNESS_FILES) + +$(HARNESS_FILES): runme.sh runme.tcl ./runme.sh +copy: $(HARNESS_FILES) + mkdir -p $(HARNESS_DIR) + cp $(HARNESS_FILES) $(HARNESS_DIR) + clean: - rm -rf specimen_[0-9][0-9][0-9]/ seg_clblx.segbits vivado*.log vivado_*.str vivado*.jou design *.bits *.dcp *.bit design.txt .Xil - rm -rf $(BUILD_DIR) *~ + rm -rf $(BUILD_DIR) $(HARNESS_DIR) -.PHONY: all clean +.PHONY: all clean copy diff --git a/minitests/roi_harness/bit2fasm.sh b/minitests/roi_harness/bit2fasm.sh index 235d6888..41946c06 100755 --- a/minitests/roi_harness/bit2fasm.sh +++ b/minitests/roi_harness/bit2fasm.sh @@ -3,5 +3,5 @@ set -ex BIT_IN=$1 BITS=$(tempfile --suffix .bits) -${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o ${BITS} -z -y ${BIT_IN} +${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o ${BITS} -z -y ${BIT_IN} > /dev/null ${XRAY_BITS2FASM} ${BITS} diff --git a/minitests/roi_harness/create_design_json.py b/minitests/roi_harness/create_design_json.py index a6717dad..1d127f70 100644 --- a/minitests/roi_harness/create_design_json.py +++ b/minitests/roi_harness/create_design_json.py @@ -2,6 +2,19 @@ import json import csv import argparse import sys +from prjxray.db import Database +from prjxray.roi import Roi +from prjxray.util import get_db_root + + +def set_port_wires(ports, name, pin, wires_outside_roi): + for port in ports: + if name == port['name']: + port['wires_outside_roi'] = wires_outside_roi + assert port['pin'] == pin + return + + assert False, name def main(): @@ -10,6 +23,7 @@ def main(): "Creates design.json from output of ROI generation tcl script.") parser.add_argument('--design_txt', required=True) parser.add_argument('--design_info_txt', required=True) + parser.add_argument('--pad_wires', required=True) args = parser.parse_args() @@ -26,6 +40,36 @@ def main(): j['info'][name] = int(value) + db = Database(get_db_root()) + grid = db.grid() + + roi = Roi( + db=db, + x1=j['info']['GRID_X_MIN'], + y1=j['info']['GRID_Y_MIN'], + x2=j['info']['GRID_X_MAX'], + y2=j['info']['GRID_Y_MAX'], + ) + + with open(args.pad_wires) as f: + for l in f: + parts = l.strip().split(' ') + name = parts[0] + pin = parts[1] + wires = parts[2:] + + wires_outside_roi = [] + + for wire in wires: + tile = wire.split('/')[0] + + loc = grid.loc_of_tilename(tile) + + if not roi.tile_in_roi(loc): + wires_outside_roi.append(wire) + + set_port_wires(j['ports'], name, pin, wires_outside_roi) + json.dump(j, sys.stdout, indent=2, sort_keys=True) diff --git a/minitests/roi_harness/runme.sh b/minitests/roi_harness/runme.sh index 8ec24515..e6034ccc 100755 --- a/minitests/roi_harness/runme.sh +++ b/minitests/roi_harness/runme.sh @@ -30,14 +30,13 @@ if [ "$SMALL" = Y ] ; then export DIN_N=8 export DOUT_N=8 export XRAY_ROI=SLICE_X12Y100:SLICE_X17Y117 -# 16x by 50y CLBs (800) +# All of CMT X0Y2 else echo "Design: large" - export PITCH=3 - export DIN_N=8 - export DOUT_N=8 - export XRAY_ROI=SLICE_X12Y100:SLICE_X27Y149 - #export XRAY_ROI=SLICE_X12Y100:SLICE_X5Y149 + export PITCH=2 + export DIN_N=16 + export DOUT_N=16 + export XRAY_ROI=SLICE_X0Y100:SLICE_X35Y149 fi mkdir -p $BUILD_DIR @@ -60,7 +59,7 @@ ${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o design.bits -z -y design.bit ${XRAY_SEGPRINT} -zd design.bits >design.segp ${XRAY_DIR}/utils/bits2fasm.py --verbose design.bits > design.fasm ${XRAY_DIR}/utils/fasm2frames.py design.fasm design.frm -python3 ../create_design_json.py --design_info_txt design_info.txt --design_txt design.txt > design.json +python3 ../create_design_json.py --design_info_txt design_info.txt --design_txt design.txt --pad_wires design_pad_wires.txt > design.json # Hack to get around weird clock error related to clk net not found # Remove following lines: diff --git a/minitests/roi_harness/runme.tcl b/minitests/roi_harness/runme.tcl index 2a598a5e..42ff1423 100644 --- a/minitests/roi_harness/runme.tcl +++ b/minitests/roi_harness/runme.tcl @@ -31,7 +31,6 @@ set XRAY_ROI_Y1 [lindex [split "$::env(XRAY_ROI)" Y] 2] set X_BASE $XRAY_ROI_X0 set Y_BASE $XRAY_ROI_Y0 -# set Y_DIN_BASE 100 set Y_CLK_BASE $Y_BASE # Clock lut in middle set Y_DIN_BASE [expr "$Y_CLK_BASE + $PITCH"] @@ -282,22 +281,31 @@ if {$fixed_xdc eq ""} { # Place ROI inputs puts "Placing ROI inputs" - set y $Y_DIN_BASE + set y_left $Y_DIN_BASE + # Shift y_right up to avoid PCIe block that makes routing hard. + set y_right [expr {$Y_DIN_BASE + 24}] for {set i 0} {$i < $DIN_N} {incr i} { - loc_lut_in $i $x $y - set y [expr {$y + $PITCH}] + if {[net_bank_left "din[$i]"]} { + loc_lut_in $i $XRAY_ROI_X0 $y_left + set y_left [expr {$y_left + $PITCH}] + } else { + loc_lut_in $i $XRAY_ROI_X1 $y_right + set y_right [expr {$y_right + $PITCH}] + } } # Place ROI outputs - set y $Y_DOUT_BASE + set y_left $Y_DOUT_BASE + set y_right $Y_DOUT_BASE puts "Placing ROI outputs" for {set i 0} {$i < $DOUT_N} {incr i} { if {[net_bank_left "dout[$i]"]} { - loc_lut_out $i $XRAY_ROI_X0 $y + loc_lut_out $i $XRAY_ROI_X0 $y_left + set y_left [expr {$y_left + $PITCH}] } else { - loc_lut_out $i $XRAY_ROI_X1 $y + loc_lut_out $i $XRAY_ROI_X1 $y_right + set y_right [expr {$y_right + $PITCH}] } - set y [expr {$y + $PITCH}] } } @@ -373,6 +381,7 @@ close $fp # XXX: maybe add IOB? set fp [open "design.txt" w] +set fp_wires [open "design_pad_wires.txt" w] puts $fp "name node pin wire" # Manual routing if {$fixed_xdc eq ""} { @@ -391,54 +400,67 @@ if {$fixed_xdc eq ""} { puts "Routing ROI inputs" # Arbitrary offset as observed - set y [expr {$Y_DIN_BASE - 1}] + set y_left $Y_DIN_BASE + set y_right [expr {$Y_DIN_BASE + 24}] for {set i 0} {$i < $DIN_N} {incr i} { # needed to force routes away to avoid looping into ROI - #set x_EE2BEG3 [expr {$x - 2}] - set x_EE2BEG3 7 - set x_NE2BEG3 9 - set node "INT_R_X${x_NE2BEG3}Y${y}/NE2BEG3" - route_via2 "din_IBUF[$i]" "INT_R_X${x_EE2BEG3}Y${y}/EE2BEG3 $node" + if {[net_bank_left "din[$i]"]} { + set node "INT_L_X0Y${y_left}/EE2BEG2" + route_via2 "din_IBUF[$i]" "$node" + set y_left [expr {$y_left + $PITCH}] + } else { + set node "INT_R_X25Y${y_right}/WW2BEG1" + route_via2 "din_IBUF[$i]" "$node" + set y_right [expr {$y_right + $PITCH}] + } set net "din[$i]" set pin "$net2pin($net)" set wire [node2wire $node] puts $fp "$net $node $pin $wire" - set y [expr {$y + $PITCH}] + + set wires [get_wires -of_objects [get_nets "din_IBUF[$i]"]] + puts $fp_wires "$net $pin $wires" } puts "Routing ROI outputs" # Arbitrary offset as observed - set y [expr {$Y_DOUT_BASE + 0}] + set y_left [expr {$Y_DOUT_BASE + 0}] + set y_right [expr {$Y_DOUT_BASE + 0}] for {set i 0} {$i < $DOUT_N} {incr i} { if {[net_bank_left "dout[$i]"]} { # XXX: find a better solution if we need harness long term # works on 50t but not 35t if {$part eq "xc7a50tfgg484-1"} { - set node "INT_L_X10Y${y}/WW2BEG0" + set node "INT_L_X1Y${y_left}/WW2BEG0" route_via2 "roi/dout[$i]" "$node" # works on 35t but not 50t } elseif {$part eq "xc7a35tcsg324-1"} { - set node "INT_L_X10Y${y}/SW6BEG0" + set node "INT_L_X2Y${y_left}/SW6BEG0" route_via2 "roi/dout[$i]" "$node" } elseif {$part eq "xc7a35tcpg236-1"} { - set node "INT_L_X10Y${y}/SW6BEG0" + set node "INT_L_X2Y${y_left}/SW6BEG0" route_via2 "roi/dout[$i]" "$node" } else { error "Routing: unsupported part $part" } + set y_left [expr {$y_left + $PITCH}] # XXX: only care about right ports on Arty } else { - set node "INT_R_X17Y${y}/SE6BEG0" + set node "INT_R_X23Y${y_right}/LH12" route_via2 "roi/dout[$i]" "$node" + set y_right [expr {$y_right + $PITCH}] } set net "dout[$i]" set pin "$net2pin($net)" set wire [node2wire $node] puts $fp "$net $node $pin $wire" - set y [expr {$y + $PITCH}] + + set wires [get_wires -of_objects [get_nets "roi/dout[$i]"]] + puts $fp_wires "$net $pin $wires" } } close $fp +close $fp_wires puts "routing design" route_design diff --git a/prjxray/fasm_assembler.py b/prjxray/fasm_assembler.py index c625ac6c..4b633d45 100644 --- a/prjxray/fasm_assembler.py +++ b/prjxray/fasm_assembler.py @@ -22,6 +22,9 @@ class FasmAssembler(object): self.db = db self.grid = db.grid() + self.seen_tile = set() + self.frames_in_use = set() + self.frames = {} self.frames_line = {} @@ -29,7 +32,12 @@ class FasmAssembler(object): if not sparse: frames = self.frames_init() else: + # Even in sparse mode, zero all frames for any tile that is + # setting a bit. This handles the case where the tile has + # multiple frames, but the FASM only specifies some of the frames. frames = {} + for frame in self.frames_in_use: + init_frame_at_address(frames, frame) for (frame_addr, word_addr, bit_index), is_set in self.frames.items(): init_frame_at_address(frames, frame_addr) @@ -112,6 +120,13 @@ class FasmAssembler(object): segbits = self.db.get_tile_segbits(gridinfo.tile_type) + # Mark all frames used by this tile as in use. + if tile not in self.seen_tile: + for frame in segbits.frames(bits): + self.frames_in_use.add(frame) + + self.seen_tile.add(tile) + db_k = '%s.%s' % (gridinfo.tile_type, feature) try: diff --git a/prjxray/tile_segbits.py b/prjxray/tile_segbits.py index b8737b7f..8472c9f8 100644 --- a/prjxray/tile_segbits.py +++ b/prjxray/tile_segbits.py @@ -140,3 +140,9 @@ class TileSegbits(object): else: for bit in self.segbits[self.feature_addresses[feature][address]]: yield bit + + def frames(self, bits): + """ Iterate over frames this tile uses for a given bit location. """ + for query_bits in self.segbits.values(): + for bit in query_bits: + yield bits.base_address + bit.word_column diff --git a/utils/fasm2pips.py b/utils/fasm2pips.py index 9c92887b..3e7a60d8 100755 --- a/utils/fasm2pips.py +++ b/utils/fasm2pips.py @@ -46,7 +46,7 @@ def main(): for pip in tile_type.pips: if pip.net_from == parts[2] and pip.net_to == parts[1]: - yield '{}/{}.{}'.format(tile, gridinfo.tile_type, pip.name) + yield '{}/{}'.format(tile, pip.name) print( 'highlight_objects [concat {}]'.format(