407 lines
11 KiB
Tcl
407 lines
11 KiB
Tcl
|
##############################################################################
|
||
|
# Define some global variables
|
||
|
##############################################################################
|
||
|
|
||
|
if {![info exists HDL_LIBRARIES]} {
|
||
|
set HDL_LIBRARIES ()
|
||
|
}
|
||
|
set HDL_TARGET "default_target"
|
||
|
set HDL_PATH [pwd]
|
||
|
set HDL_WORK "work"
|
||
|
|
||
|
# Uncomment the following line to generate a log file for debug
|
||
|
#set HDL_LOG [open "hdl_common.log" "w"]
|
||
|
|
||
|
##############################################################################
|
||
|
# Some utilities
|
||
|
##############################################################################
|
||
|
|
||
|
# Extract first element from a list (for argument processing)
|
||
|
proc extract_first {list_name {option ""}} {
|
||
|
upvar $list_name mylist
|
||
|
if {[string length $option]>0 && [llength $mylist]==0} {
|
||
|
error "Missing argument for option $option"
|
||
|
}
|
||
|
set first [lindex $mylist 0]
|
||
|
if {[string length $option]>0 && [string match "-*" $first]} {
|
||
|
error "Missing argument for option $option"
|
||
|
}
|
||
|
set mylist [lrange $mylist 1 end]
|
||
|
return $first
|
||
|
}
|
||
|
|
||
|
# Clean-up file path
|
||
|
proc clean_path {f} {
|
||
|
# Add trailing /
|
||
|
set f "$f/"
|
||
|
# Remove double / (excepted leading)
|
||
|
while {[regsub {(.)//} $f "\1/" f]} {}
|
||
|
# Remove .
|
||
|
while {[regsub {/\./} $f "/" f]} {}
|
||
|
# Remove ..
|
||
|
while {[regsub {/[^/.]+/\.\./} $f "/" f]} {}
|
||
|
# Remove trailing /
|
||
|
regsub {/$} $f "" f
|
||
|
return $f
|
||
|
}
|
||
|
|
||
|
# Translate relative paths to absolute paths
|
||
|
proc get_full_path {files} {
|
||
|
global HDL_PATH
|
||
|
set r {}
|
||
|
# For DOS paths, replace \ by /
|
||
|
regsub -all {\\} $files "/" files
|
||
|
foreach f $files {
|
||
|
hdl_debug " $f"
|
||
|
# Append file path
|
||
|
if {[string match "/*" $f] || [string match "?:/*" $f]} {
|
||
|
# Path is an absolute path
|
||
|
hdl_warning "Using absolute path $f"
|
||
|
} else {
|
||
|
# Path is a relative path
|
||
|
set f [clean_path $HDL_PATH/$f]
|
||
|
}
|
||
|
hdl_debug " => $f"
|
||
|
lappend r $f
|
||
|
# Check access to file
|
||
|
if {![file readable $f]} {
|
||
|
error "Cannot read file $f"
|
||
|
}
|
||
|
}
|
||
|
return $r
|
||
|
}
|
||
|
|
||
|
# Check if value match any pattern in the list
|
||
|
proc match_list {mlist value} {
|
||
|
set match 0
|
||
|
foreach m $mlist {
|
||
|
if [string match $m $value] {
|
||
|
set match 1
|
||
|
}
|
||
|
}
|
||
|
return $match
|
||
|
}
|
||
|
|
||
|
proc get_lib_path {} {
|
||
|
if [file isdirectory "/cad/trash"] {
|
||
|
set libs "/cad/trash[pwd]/libs"
|
||
|
} elseif [file isdirectory "e:/trash"] {
|
||
|
set libs [pwd]
|
||
|
# Replace D:/ by D/ for local drive
|
||
|
regsub ":" $libs "" libs
|
||
|
# Remove leading // for network drive
|
||
|
regsub "//" $libs "" libs
|
||
|
set libs "e:/trash/$libs"
|
||
|
} else {
|
||
|
# No "trash" directory on this machine => work locally
|
||
|
set libs "./libs"
|
||
|
}
|
||
|
file mkdir $libs
|
||
|
return $libs
|
||
|
}
|
||
|
|
||
|
##############################################################################
|
||
|
# Procedures to display messages
|
||
|
##############################################################################
|
||
|
|
||
|
# Write message to log file if logging enabled
|
||
|
proc hdl_log { msg } {
|
||
|
global HDL_LOG
|
||
|
if [info exists HDL_LOG] {
|
||
|
puts $HDL_LOG $msg
|
||
|
flush $HDL_LOG
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
# Debug messages are sent only to log file
|
||
|
proc hdl_debug { msg } {
|
||
|
hdl_log "hdl_common - Debug: $msg"
|
||
|
return
|
||
|
}
|
||
|
|
||
|
# According to the tool, "puts" or "echo" should be used
|
||
|
# HDL_PUTS variable is used for this purpose
|
||
|
# All message are also sent to log file
|
||
|
proc hdl_puts { msg } {
|
||
|
global HDL_PUTS
|
||
|
$HDL_PUTS $msg
|
||
|
hdl_log $msg
|
||
|
return
|
||
|
}
|
||
|
|
||
|
proc hdl_note { msg } {
|
||
|
hdl_puts "hdl_common - Note: $msg"
|
||
|
return
|
||
|
}
|
||
|
|
||
|
proc hdl_warning { msg } {
|
||
|
hdl_puts "hdl_common - Warning: $msg"
|
||
|
return
|
||
|
}
|
||
|
|
||
|
proc hdl_message { args } {
|
||
|
global HDL_MSG_FORMAT
|
||
|
hdl_puts [format $HDL_MSG_FORMAT [join $args " "]]
|
||
|
return
|
||
|
}
|
||
|
|
||
|
##############################################################################
|
||
|
# Procedures for compilation scripts
|
||
|
##############################################################################
|
||
|
|
||
|
# Compile source files
|
||
|
proc hdl_compile { args } {
|
||
|
global HDL_TOOLTYPE HDL_TOOLNAME HDL_TARGET HDL_LIBRARIES HDL_WORK
|
||
|
# Default values
|
||
|
set format ""
|
||
|
set version "93"
|
||
|
set files {}
|
||
|
set incdirs {}
|
||
|
set only_for {}
|
||
|
set not_for {}
|
||
|
set toolname {}
|
||
|
set tooltype "*"
|
||
|
set library $HDL_WORK
|
||
|
set define {}
|
||
|
set behavioral 0
|
||
|
|
||
|
# Decode arguments
|
||
|
while {[llength $args]} {
|
||
|
set arg [extract_first args]
|
||
|
switch -glob -- $arg {
|
||
|
"-f" {
|
||
|
set format [extract_first args "-f"]
|
||
|
}
|
||
|
"-v" {
|
||
|
set version [extract_first args "-version"]
|
||
|
}
|
||
|
"-only_for" {
|
||
|
set only_for [concat $only_for [extract_first args "-only_for"]]
|
||
|
}
|
||
|
"-not_for" {
|
||
|
set not_for [concat $not_for [extract_first args "-not_for"]]
|
||
|
}
|
||
|
"-sim" {
|
||
|
set tooltype "SIMULATION"
|
||
|
set behavioral 1
|
||
|
}
|
||
|
"-syn" {
|
||
|
set tooltype "SYNTHESIS"
|
||
|
set behavioral 0
|
||
|
}
|
||
|
"-tool" {
|
||
|
set toolname [concat $toolname [extract_first args "-tool"]]
|
||
|
}
|
||
|
"-incdir" {
|
||
|
set incdirs [concat $incdirs [extract_first args "-incdir"]]
|
||
|
}
|
||
|
"-lib" {
|
||
|
set library [extract_first args "-lib"]
|
||
|
if {[string match "work" $library]} {
|
||
|
hdl_warning "Specifying '-lib work' is useless"
|
||
|
}
|
||
|
}
|
||
|
"-define" {
|
||
|
set define [concat $define [extract_first args "-define"]]
|
||
|
}
|
||
|
"-*" {
|
||
|
error "Unsupported argument $arg"
|
||
|
}
|
||
|
default {
|
||
|
set files [concat $files $arg]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
# Check arguments
|
||
|
if {![llength $files]} {
|
||
|
error "No file to compile"
|
||
|
}
|
||
|
# If no "-only_for" option given, use file for any target
|
||
|
if {[llength $only_for]==0} {
|
||
|
set only_for {*}
|
||
|
}
|
||
|
# If no "-tool" option given, use file for any tool
|
||
|
if {[llength $toolname]==0} {
|
||
|
set toolname {*}
|
||
|
}
|
||
|
|
||
|
# Check if compilation is required
|
||
|
if {[match_list $only_for $HDL_TARGET] && ![match_list $not_for $HDL_TARGET] &&
|
||
|
[string match $tooltype $HDL_TOOLTYPE] && [match_list $toolname $HDL_TOOLNAME]} {
|
||
|
# Create library if needed
|
||
|
if {[lsearch -exact $HDL_LIBRARIES $library]<0} {
|
||
|
hdl_note "Creating library $library"
|
||
|
lappend HDL_LIBRARIES $library
|
||
|
hdl_tool_library $library
|
||
|
}
|
||
|
# Compile files
|
||
|
foreach f $files {
|
||
|
# Warning if dummy file is used
|
||
|
if {[string match "*dummy*" [string tolower $f]]} {
|
||
|
hdl_note "Using [file tail $f]"
|
||
|
}
|
||
|
# Determine format
|
||
|
if {![llength $format]} {
|
||
|
if {[string match "*.vh?*" $f]} {
|
||
|
set format "vhdl"
|
||
|
} elseif {[string match "*.v*" $f]} {
|
||
|
set format "verilog"
|
||
|
set version "sv"
|
||
|
} elseif {[string match "*.sv" $f]} {
|
||
|
set format "verilog"
|
||
|
set version "sv"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
hdl_tool_compile $format $version [get_full_path $incdirs] $library $define [get_full_path $files] $behavioral
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
# Change directory
|
||
|
proc hdl_cd { path } {
|
||
|
global HDL_PATH
|
||
|
set HDL_PATH [get_full_path $path]
|
||
|
hdl_debug "New path is $HDL_PATH"
|
||
|
return
|
||
|
}
|
||
|
|
||
|
# Execute script
|
||
|
proc hdl_source { args } {
|
||
|
global HDL_PATH HDL_TARGET HDL_WORK HDL_TOOLTYPE HDL_TOOLNAME
|
||
|
# Save original values
|
||
|
set save_path $HDL_PATH
|
||
|
set save_target $HDL_TARGET
|
||
|
set save_work $HDL_WORK
|
||
|
# Default value
|
||
|
set files {}
|
||
|
set toolname {}
|
||
|
set tooltype "*"
|
||
|
set only_for {}
|
||
|
set not_for {}
|
||
|
# Process options
|
||
|
while {[llength $args]} {
|
||
|
set arg [extract_first args]
|
||
|
switch -glob -- $arg {
|
||
|
"-lib" {
|
||
|
set HDL_WORK [extract_first args "-lib"]
|
||
|
if {[string match "work" $HDL_WORK]} {
|
||
|
hdl_warning "Specifying '-lib work' is useless"
|
||
|
}
|
||
|
}
|
||
|
"-target" {
|
||
|
set HDL_TARGET [extract_first args "-target"]
|
||
|
}
|
||
|
"-sim" {
|
||
|
set tooltype "SIMULATION"
|
||
|
set behavioral 1
|
||
|
}
|
||
|
"-syn" {
|
||
|
set tooltype "SYNTHESIS"
|
||
|
set behavioral 0
|
||
|
}
|
||
|
"-tool" {
|
||
|
set toolname [concat $toolname [extract_first args "-tool"]]
|
||
|
}
|
||
|
"-only_for" {
|
||
|
set only_for [concat $only_for [extract_first args "-only_for"]]
|
||
|
}
|
||
|
"-not_for" {
|
||
|
set not_for [concat $not_for [extract_first args "-not_for"]]
|
||
|
}
|
||
|
"-*" {
|
||
|
error "Unsupported argument $arg"
|
||
|
}
|
||
|
default {
|
||
|
set files [concat $files $arg]
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
# Check arguments
|
||
|
if {![llength $files]} {
|
||
|
error "No script specified"
|
||
|
}
|
||
|
# If no "-only_for" option given, use file for any target
|
||
|
if {[llength $only_for]==0} {
|
||
|
set only_for {*}
|
||
|
}
|
||
|
# If no "-tool" option given, use file for any tool
|
||
|
if {[llength $toolname]==0} {
|
||
|
set toolname {*}
|
||
|
}
|
||
|
|
||
|
# Check if compilation is required
|
||
|
if {[match_list $only_for $HDL_TARGET] && ![match_list $not_for $HDL_TARGET] &&
|
||
|
[string match $tooltype $HDL_TOOLTYPE] && [match_list $toolname $HDL_TOOLNAME]} {
|
||
|
# Source scripts
|
||
|
foreach script $files {
|
||
|
# Change directory to script location
|
||
|
hdl_cd [file dirname $script]
|
||
|
# Execute script
|
||
|
set script [get_full_path [file tail $script]]
|
||
|
hdl_note "Source $script ($HDL_TARGET)"
|
||
|
uplevel source $script
|
||
|
# Restore original path
|
||
|
set HDL_PATH $save_path
|
||
|
hdl_debug "Back to directory $HDL_PATH"
|
||
|
}
|
||
|
}
|
||
|
# Restore original values
|
||
|
set HDL_TARGET $save_target
|
||
|
set HDL_WORK $save_work
|
||
|
#puts "Back to $HDL_PATH"
|
||
|
return
|
||
|
}
|
||
|
|
||
|
# Specify target
|
||
|
proc hdl_set_target { args } {
|
||
|
global HDL_TARGET env
|
||
|
# Default values
|
||
|
set use_env 0
|
||
|
set default ""
|
||
|
set target ""
|
||
|
# Decode arguments
|
||
|
while {[llength $args]} {
|
||
|
set arg [extract_first args]
|
||
|
switch -glob -- $arg {
|
||
|
"-env" {
|
||
|
set use_env 1
|
||
|
}
|
||
|
"-default" {
|
||
|
set default [extract_first args "-default"]
|
||
|
}
|
||
|
"-*" {
|
||
|
error "Unsupported argument $arg"
|
||
|
}
|
||
|
default {
|
||
|
set target $arg
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
# Check arguments
|
||
|
if {[llength $target]} {
|
||
|
set HDL_TARGET $target
|
||
|
hdl_note "Using target $HDL_TARGET"
|
||
|
} elseif {$use_env} {
|
||
|
if {[info exists env(HDL_TARGET)]} {
|
||
|
set HDL_TARGET $env(HDL_TARGET)
|
||
|
hdl_note "Using target $HDL_TARGET (from environment variable HDL_TARGET)"
|
||
|
} elseif {[llength $default]} {
|
||
|
set HDL_TARGET $default
|
||
|
hdl_note "Using default target $HDL_TARGET (environment variable HDL_TARGET not defined)"
|
||
|
} else {
|
||
|
error "No environment variable defined and no default target"
|
||
|
}
|
||
|
} else {
|
||
|
error "Missing argument"
|
||
|
}
|
||
|
return
|
||
|
}
|
||
|
|
||
|
##############################################################################
|
||
|
|
||
|
# clock is an invalid command name for Synplify at least until version 2010.09
|
||
|
# hdl_debug [clock format [clock seconds]]
|