|
| 1 | +# Back-annotation script. Version 1.3. Janary 16th, 2012. by Ryan Scoville |
| 2 | +# To run, make sure Quartus II project is closed, and type at command prompt: |
| 3 | +# quartus_cdb -t ba.tcl |
| 4 | + |
| 5 | +###### User Variables ####### |
| 6 | +# Variable project_name is the name of the .qpf without the extension. Also can be "auto_find". |
| 7 | +set project_name "auto_find" |
| 8 | + |
| 9 | +# Wildcard or list of wild cards that nodes must match in order to be back-annotated. Case sensitive. |
| 10 | +set name_wildcards {*} |
| 11 | + |
| 12 | +# Wildcard or list of wilcards that node location must match in order to be back-annotated. Examples: |
| 13 | +# set location_wildcards {PIN_*} ;# Locks down all the top-level I/O ports |
| 14 | +# set location_wildcards {M9K* M144K* M20K*} ;# Locks down all the hard memory blocks for Stratix IV/V. |
| 15 | +# set location_wildcards {DSP*} ;# Locks down all the DSP blocks |
| 16 | +# set location_wildcards {PLL*} ;# Locks down all the PLL Locations |
| 17 | +# set location_wildcards {CLKCTRL_*} ;# Locks down all the clock trees |
| 18 | +set location_wildcards {*} |
| 19 | + |
| 20 | +# The following demotes specific location assignments like FF_X34_Y22_N4 to X34_Y22, i.e. to the LAB. This should not hurt timing and gives |
| 21 | +# flexibility to the router. Currently only demotes location names matching FF_, LABCELL_ and MLABCELL_, which are used in 28nm families. Older |
| 22 | +# families may not work as they have different location naming conventions. |
| 23 | +set demote_logic_location_to_LAB 1 |
| 24 | + |
| 25 | +# Assignment appended with this comment, making it easier to find/sort/delete these assignments in the .qsf and especially the Assignment Editor |
| 26 | +set comment from_ba.tcl |
| 27 | + |
| 28 | +# If debug set to 1, "puts" the assignments into a file called ba_assignments.tcl, but does not modify the project in any way. |
| 29 | +# The assignments can then be copied into the .qsf, or the ba_assignments.tcl can be sourced from within Quartus. This will append assignments if ba_assignments.tcl already exists. |
| 30 | +set debug 1 |
| 31 | +############################## |
| 32 | + |
| 33 | +##### Usage ####### |
| 34 | +# This script back-annotates nodes in a design based on name and location wildcards that the user chooses. |
| 35 | +# Note that Quartus II Assignments -> Back-Annotate from the menu already allows the user to lock down top-level ports in the design, or everything. This |
| 36 | +# script provides a little more control. In general, it is not recommended to lock down a large number of nodes inside the FPGA. Node names often change |
| 37 | +# during synthesis, and locking down portions of the design can limit what the fitter can do. The original intent of this script is to allow the user to |
| 38 | +# lock down all the memories and DSP in a design. Theoretically, after doing a seed sweep and locking down the memories and DSP of the best result, |
| 39 | +# the user can "anchor" the fitter into getting similar results. Of course this is design dependent. (The design I ran it on had less variation and on average gave |
| 40 | +# better results than the un-anchored compiles, but the very best result was from the unanchored seed sweep.) |
| 41 | +# I have also used this script to quickly lock down PLLs and global clock trees. I am sure user's will find their own applications. Incremental Compilation |
| 42 | +# is recommended for locking down hierarchies of the design. |
| 43 | +################### |
| 44 | + |
| 45 | +proc demote_logic_to_LAB {loc} { |
| 46 | + if {[regexp {^(FF_X)([0-9]+)(_Y)([0-9]+)} $loc a b x_loc d y_loc]} { |
| 47 | + set loc "X$x_loc\_Y$y_loc" |
| 48 | + } elseif {[regexp {^(LABCELL_X)([0-9]+)(_Y)([0-9]+)} $loc a b x_loc d y_loc]} { |
| 49 | + set loc "X$x_loc\_Y$y_loc" |
| 50 | + } elseif {[regexp {^(MLABCELL_X)([0-9]+)(_Y)([0-9]+)} $loc a b x_loc d y_loc]} { |
| 51 | + set loc "X$x_loc\_Y$y_loc" |
| 52 | + } |
| 53 | + return $loc |
| 54 | +} |
| 55 | + |
| 56 | +############################################ |
| 57 | +# Auto find the project name to open, if there is only one project in the directory(which is good practice...) |
| 58 | +if {$project_name == "auto_find"} { |
| 59 | + set qpf [glob *.qpf] |
| 60 | + set num_quartus_projects [llength $qpf] |
| 61 | + if {$num_quartus_projects == 0} { |
| 62 | + puts "There is no .qpf in this directory. No project to open." |
| 63 | + } elseif {$num_quartus_projects == 1} { |
| 64 | + set project_name [file rootname $qpf] |
| 65 | + } else { |
| 66 | + puts "There is more than one *.qpf in this project: $qpf" |
| 67 | + puts "Open remove_qip_from_project.tcl, uncomment line 1, and change project_name from auto_find to .qpf name. For example, if project is called my_top.qpf, set line 1 to:" |
| 68 | + puts "set project_name my_top.qpf" |
| 69 | + exit |
| 70 | + } |
| 71 | +} elseif {![file exists "$project_name\.qpf"]} { |
| 72 | + puts "Variable project_name was set to $project_name, but $project_name\.qpf could not be found in directory." |
| 73 | + exit |
| 74 | +} |
| 75 | +project_open $project_name -current_revision ;# -force ;# In one case I needed to use -force option even though opening with same version of Quartus. |
| 76 | + |
| 77 | + |
| 78 | +load_package chip_planner |
| 79 | +read_netlist |
| 80 | + |
| 81 | +set_batch_mode on |
| 82 | + |
| 83 | +if {$debug == 1} { |
| 84 | + set outfile [open ba_assignments.tcl a] |
| 85 | +} |
| 86 | + |
| 87 | +set matched_nodes 0 |
| 88 | +set assign_name "" |
| 89 | +set assign_loc "" |
| 90 | + |
| 91 | +# User name match wildcards often have [] in their name, but that has special meaning when doing a "string match $wildcard name". |
| 92 | +# The following replaces [ with \[ and ] with \] so it works. |
| 93 | +set newname_wildcards "" |
| 94 | +foreach name $name_wildcards { |
| 95 | + regsub -all {]} $name {\]} name |
| 96 | + regsub -all {\[} $name {\[} name |
| 97 | + lappend newname_wildcards $name |
| 98 | +} |
| 99 | + |
| 100 | +set all_nodes [get_nodes -type all] |
| 101 | +foreach_in_collection node $all_nodes { |
| 102 | + set node_name [get_node_info -node $node -info name] |
| 103 | + set node_loc [get_node_info -node $node -info "Location String"] |
| 104 | + set name_matches 0 |
| 105 | + set loc_matches 0 |
| 106 | +#puts $outfile "$node_name $node_loc" |
| 107 | + foreach name $newname_wildcards { |
| 108 | + if {[string match $name $node_name]} { |
| 109 | + set name_matches 1 |
| 110 | +#puts $outfile " name=$name" |
| 111 | +#puts $outfile "node_name=$node_name" |
| 112 | + break |
| 113 | + } |
| 114 | + } |
| 115 | + foreach loc $location_wildcards { |
| 116 | + if {[string match $loc $node_loc]} { |
| 117 | + set loc_matches 1 |
| 118 | + break |
| 119 | + } |
| 120 | + } |
| 121 | + if {($name_matches == 1) && ($loc_matches)} { |
| 122 | +#puts $outfile "MATCH!!!!" |
| 123 | + set assign_name $node_name |
| 124 | + set assign_loc $node_loc |
| 125 | + if {$demote_logic_location_to_LAB} { |
| 126 | + set assign_loc [demote_logic_to_LAB $assign_loc] |
| 127 | + } |
| 128 | + incr matched_nodes |
| 129 | + if {$debug == 1} { |
| 130 | + puts $outfile "set_location_assignment $assign_loc -to $assign_name -comment $comment" |
| 131 | + } elseif {$debug == 0} { |
| 132 | + set_location_assignment $assign_loc -to $assign_name -comment $comment |
| 133 | + } else { |
| 134 | + puts {Errors: Variable debug was not "1" or "0"} |
| 135 | + break |
| 136 | + } |
| 137 | + } |
| 138 | +} |
| 139 | +puts "Found $matched_nodes nodes that match name $name_wildcards and location $location_wildcards." |
| 140 | +if {$debug == 1} { |
| 141 | + puts $outfile "#Found $matched_nodes nodes that match name $name_wildcards and location $location_wildcards." |
| 142 | + close $outfile |
| 143 | +} |
| 144 | + |
| 145 | +set_batch_mode off |
| 146 | +project_close |
| 147 | + |
0 commit comments