mirror of
https://github.com/pConst/basic_verilog.git
synced 2025-01-14 06:42:54 +08:00
148 lines
6.5 KiB
Tcl
Executable File
148 lines
6.5 KiB
Tcl
Executable File
# Back-annotation script. Version 1.3. Janary 16th, 2012. by Ryan Scoville
|
|
# To run, make sure Quartus II project is closed, and type at command prompt:
|
|
# quartus_cdb -t ba.tcl
|
|
|
|
###### User Variables #######
|
|
# Variable project_name is the name of the .qpf without the extension. Also can be "auto_find".
|
|
set project_name "auto_find"
|
|
|
|
# Wildcard or list of wild cards that nodes must match in order to be back-annotated. Case sensitive.
|
|
set name_wildcards {*}
|
|
|
|
# Wildcard or list of wilcards that node location must match in order to be back-annotated. Examples:
|
|
# set location_wildcards {PIN_*} ;# Locks down all the top-level I/O ports
|
|
# set location_wildcards {M9K* M144K* M20K*} ;# Locks down all the hard memory blocks for Stratix IV/V.
|
|
# set location_wildcards {DSP*} ;# Locks down all the DSP blocks
|
|
# set location_wildcards {PLL*} ;# Locks down all the PLL Locations
|
|
# set location_wildcards {CLKCTRL_*} ;# Locks down all the clock trees
|
|
set location_wildcards {*}
|
|
|
|
# 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
|
|
# flexibility to the router. Currently only demotes location names matching FF_, LABCELL_ and MLABCELL_, which are used in 28nm families. Older
|
|
# families may not work as they have different location naming conventions.
|
|
set demote_logic_location_to_LAB 1
|
|
|
|
# Assignment appended with this comment, making it easier to find/sort/delete these assignments in the .qsf and especially the Assignment Editor
|
|
set comment from_ba.tcl
|
|
|
|
# If debug set to 1, "puts" the assignments into a file called ba_assignments.tcl, but does not modify the project in any way.
|
|
# 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.
|
|
set debug 1
|
|
##############################
|
|
|
|
##### Usage #######
|
|
# This script back-annotates nodes in a design based on name and location wildcards that the user chooses.
|
|
# 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
|
|
# 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
|
|
# 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
|
|
# 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,
|
|
# 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
|
|
# better results than the un-anchored compiles, but the very best result was from the unanchored seed sweep.)
|
|
# 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
|
|
# is recommended for locking down hierarchies of the design.
|
|
###################
|
|
|
|
proc demote_logic_to_LAB {loc} {
|
|
if {[regexp {^(FF_X)([0-9]+)(_Y)([0-9]+)} $loc a b x_loc d y_loc]} {
|
|
set loc "X$x_loc\_Y$y_loc"
|
|
} elseif {[regexp {^(LABCELL_X)([0-9]+)(_Y)([0-9]+)} $loc a b x_loc d y_loc]} {
|
|
set loc "X$x_loc\_Y$y_loc"
|
|
} elseif {[regexp {^(MLABCELL_X)([0-9]+)(_Y)([0-9]+)} $loc a b x_loc d y_loc]} {
|
|
set loc "X$x_loc\_Y$y_loc"
|
|
}
|
|
return $loc
|
|
}
|
|
|
|
############################################
|
|
# Auto find the project name to open, if there is only one project in the directory(which is good practice...)
|
|
if {$project_name == "auto_find"} {
|
|
set qpf [glob *.qpf]
|
|
set num_quartus_projects [llength $qpf]
|
|
if {$num_quartus_projects == 0} {
|
|
puts "There is no .qpf in this directory. No project to open."
|
|
} elseif {$num_quartus_projects == 1} {
|
|
set project_name [file rootname $qpf]
|
|
} else {
|
|
puts "There is more than one *.qpf in this project: $qpf"
|
|
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:"
|
|
puts "set project_name my_top.qpf"
|
|
exit
|
|
}
|
|
} elseif {![file exists "$project_name\.qpf"]} {
|
|
puts "Variable project_name was set to $project_name, but $project_name\.qpf could not be found in directory."
|
|
exit
|
|
}
|
|
project_open $project_name -current_revision ;# -force ;# In one case I needed to use -force option even though opening with same version of Quartus.
|
|
|
|
|
|
load_package chip_planner
|
|
read_netlist
|
|
|
|
set_batch_mode on
|
|
|
|
if {$debug == 1} {
|
|
set outfile [open ba_assignments.tcl a]
|
|
}
|
|
|
|
set matched_nodes 0
|
|
set assign_name ""
|
|
set assign_loc ""
|
|
|
|
# User name match wildcards often have [] in their name, but that has special meaning when doing a "string match $wildcard name".
|
|
# The following replaces [ with \[ and ] with \] so it works.
|
|
set newname_wildcards ""
|
|
foreach name $name_wildcards {
|
|
regsub -all {]} $name {\]} name
|
|
regsub -all {\[} $name {\[} name
|
|
lappend newname_wildcards $name
|
|
}
|
|
|
|
set all_nodes [get_nodes -type all]
|
|
foreach_in_collection node $all_nodes {
|
|
set node_name [get_node_info -node $node -info name]
|
|
set node_loc [get_node_info -node $node -info "Location String"]
|
|
set name_matches 0
|
|
set loc_matches 0
|
|
#puts $outfile "$node_name $node_loc"
|
|
foreach name $newname_wildcards {
|
|
if {[string match $name $node_name]} {
|
|
set name_matches 1
|
|
#puts $outfile " name=$name"
|
|
#puts $outfile "node_name=$node_name"
|
|
break
|
|
}
|
|
}
|
|
foreach loc $location_wildcards {
|
|
if {[string match $loc $node_loc]} {
|
|
set loc_matches 1
|
|
break
|
|
}
|
|
}
|
|
if {($name_matches == 1) && ($loc_matches)} {
|
|
#puts $outfile "MATCH!!!!"
|
|
set assign_name $node_name
|
|
set assign_loc $node_loc
|
|
if {$demote_logic_location_to_LAB} {
|
|
set assign_loc [demote_logic_to_LAB $assign_loc]
|
|
}
|
|
incr matched_nodes
|
|
if {$debug == 1} {
|
|
puts $outfile "set_location_assignment $assign_loc -to $assign_name -comment $comment"
|
|
} elseif {$debug == 0} {
|
|
set_location_assignment $assign_loc -to $assign_name -comment $comment
|
|
} else {
|
|
puts {Errors: Variable debug was not "1" or "0"}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
puts "Found $matched_nodes nodes that match name $name_wildcards and location $location_wildcards."
|
|
if {$debug == 1} {
|
|
puts $outfile "#Found $matched_nodes nodes that match name $name_wildcards and location $location_wildcards."
|
|
close $outfile
|
|
}
|
|
|
|
set_batch_mode off
|
|
project_close
|
|
|