mirror of https://github.com/openXC7/prjxray.git
Merge pull request #205 from litghost/larger_roi
Expand ROI to all of CMT X0Y2.
This commit is contained in:
commit
26b95fb46e
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Reference in New Issue