|  | # Copyright (C) 2017-2020  The Project X-Ray Authors | 
|  | # | 
|  | # Use of this source code is governed by a ISC-style | 
|  | # license that can be found in the LICENSE file or at | 
|  | # https://opensource.org/licenses/ISC | 
|  | # | 
|  | # SPDX-License-Identifier: ISC | 
|  | proc min_ysite { duts_in_column } { | 
|  | # Given a list of sites, return the one with the lowest Y coordinate | 
|  |  | 
|  | set min_dut_y 9999999 | 
|  |  | 
|  | foreach dut $duts_in_column { | 
|  | # Ex: SLICE_X2Y50/A6LUT | 
|  | # Ex: IOB_X1Y50 | 
|  | regexp ".*_X([0-9]+)Y([0-9]+)" $dut match dut_x dut_y | 
|  |  | 
|  | if { $dut_y < $min_dut_y } { | 
|  | set selected_dut $dut | 
|  | set min_dut_y $dut_y | 
|  | } | 
|  | } | 
|  | return $selected_dut | 
|  | } | 
|  |  | 
|  | proc group_dut_cols { duts ypitch } { | 
|  | # Group a list of sites into pitch sized buckets | 
|  | # Ex: IOBs occur 75 to a CMT column | 
|  | # Set pitch to 75 to get 0-74 in one bucket, 75-149 in a second, etc | 
|  | # X0Y0 {IOB_X0Y49 IOB_X0Y48 IOB_X0Y47 ... } | 
|  | # Anything with a different x is automatically in a different bucket | 
|  |  | 
|  | # LOC one LUT (a "selected_lut") into each CLB segment configuration column (ie 50 per CMT column) | 
|  | set dut_columns "" | 
|  | foreach dut $duts { | 
|  | # Ex: SLICE_X2Y50/A6LUT | 
|  | # Ex: IOB_X1Y50 | 
|  | regexp ".*_X([0-9]+)Y([0-9]+)" $dut match dut_x dut_y | 
|  |  | 
|  | # 75 per column => 0, 75, 150, etc | 
|  | set y_column [expr ($dut_y / $ypitch) * $ypitch] | 
|  | dict append dut_columns "X${dut_x}Y${y_column}" "$dut " | 
|  | } | 
|  | return $dut_columns | 
|  | } | 
|  |  | 
|  | proc loc_dut_col_bels { dut_columns cellpre cellpost } { | 
|  | # set cellpre di | 
|  |  | 
|  | # Pick the smallest Y in each column and LOC a cell to it | 
|  | # cells must be named like $cellpre[$dut_index] | 
|  | # Return the selected sites | 
|  |  | 
|  | set ret_bels {} | 
|  | set dut_index 0 | 
|  |  | 
|  | dict for {column duts_in_column} $dut_columns { | 
|  | set sel_bel_str [min_ysite $duts_in_column] | 
|  | set sel_bel [get_bels $sel_bel_str] | 
|  | if {"$sel_bel" == ""} {error "Bad bel $sel_bel from bel str $sel_bel_str"} | 
|  | set sel_site [get_sites -of_objects $sel_bel] | 
|  | if {"$sel_site" == ""} {error "Bad site $sel_site from bel $sel_bel"} | 
|  |  | 
|  | set cell [get_cells $cellpre$dut_index$cellpost] | 
|  | puts "LOCing cell $cell to site $sel_site (from bel $sel_bel)" | 
|  | set_property LOC $sel_site $cell | 
|  |  | 
|  | set dut_index [expr $dut_index + 1] | 
|  | lappend ret_bels $sel_bel | 
|  | } | 
|  |  | 
|  | return $ret_bels | 
|  | } | 
|  |  | 
|  | proc loc_dut_col_sites { dut_columns cellpre cellpost } { | 
|  | set bels [loc_dut_col_bels $dut_columns $cellpre $cellpost] | 
|  | set sites [get_sites -of_objects $bels] | 
|  | return $sites | 
|  | } | 
|  |  | 
|  | proc make_io_pad_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_pad_sites $site $pad | 
|  | } | 
|  | } | 
|  | return $io_pad_sites | 
|  | } | 
|  |  | 
|  | proc make_iob_pads {} { | 
|  | set io_pad_sites [make_io_pad_sites] | 
|  |  | 
|  | set iopad "" | 
|  | dict for {key value} $io_pad_sites { | 
|  | # Some sites have more than one pad? | 
|  | lappend iopad [lindex $value 0] | 
|  | } | 
|  | return $iopad | 
|  | } | 
|  |  | 
|  | proc make_iob_sites {} { | 
|  | set io_pad_sites [make_io_pad_sites] | 
|  |  | 
|  | set sites "" | 
|  | dict for {key value} $io_pad_sites { | 
|  | lappend sites $key | 
|  | } | 
|  | return $sites | 
|  | } | 
|  |  | 
|  | proc assign_iobs_old {} { | 
|  | set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk] | 
|  | set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports di] | 
|  | set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports do] | 
|  | set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports stb] | 
|  | } | 
|  |  | 
|  | proc assign_iobs {} { | 
|  | # Set all I/Os on the bus to valid values somewhere on the chip | 
|  | # The iob fuzzer sets these to more specific values | 
|  |  | 
|  | # All possible IOs | 
|  | set iopad [make_iob_pads] | 
|  | # Basic pins | 
|  | # XXX: not all pads are valid, but seems to be working for now | 
|  | # Maybe better to set to XRAY_PIN_* and take out of the list? | 
|  | set_property -dict "PACKAGE_PIN [lindex $iopad 0] IOSTANDARD LVCMOS33" [get_ports clk] | 
|  | set_property -dict "PACKAGE_PIN [lindex $iopad 1] IOSTANDARD LVCMOS33" [get_ports do] | 
|  | set_property -dict "PACKAGE_PIN [lindex $iopad 2] IOSTANDARD LVCMOS33" [get_ports stb] | 
|  |  | 
|  | # din bus | 
|  | set fixed_pins 3 | 
|  | set iports [get_ports di*] | 
|  | for {set i 0} {$i < [llength $iports]} {incr i} { | 
|  | set pad [lindex $iopad [expr $i+$fixed_pins]] | 
|  | set port [lindex $iports $i] | 
|  | set_property -dict "PACKAGE_PIN $pad IOSTANDARD LVCMOS33" $port | 
|  | } | 
|  | } | 
|  |  | 
|  | proc make_project {} { | 
|  | # Generate .bit only over ROI | 
|  | make_project_roi XRAY_ROI_TILEGRID XRAY_EXCLUDE_ROI_TILEGRID | 
|  | } | 
|  |  | 
|  | proc make_project_roi { roi_var exclude_roi_var } { | 
|  | # 6 CMTs in our reference part | 
|  | # What is the largest? | 
|  | set n_di 16 | 
|  |  | 
|  | create_project -force -part $::env(XRAY_PART) design design | 
|  |  | 
|  | read_verilog "$::env(FUZDIR)/top.v" | 
|  | synth_design -top top -verilog_define N_DI=$n_di | 
|  |  | 
|  | assign_iobs | 
|  |  | 
|  | create_pblock roi | 
|  | add_cells_to_pblock [get_pblocks roi] [get_cells roi] | 
|  | foreach roi "$::env($roi_var)" { | 
|  | puts "ROI: $roi" | 
|  | resize_pblock [get_pblocks roi] -add "$roi" | 
|  | } | 
|  |  | 
|  | create_pblock exclude_roi | 
|  | add_cells_to_pblock [get_pblocks roi] [get_cells roi] | 
|  | foreach roi "$::env($exclude_roi_var)" { | 
|  | puts "ROI: $roi" | 
|  | resize_pblock [get_pblocks exclude_roi] -add "$roi" | 
|  | } | 
|  |  | 
|  | 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 | 
|  |  | 
|  | set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF] | 
|  | } |