Initial commit of public repository open_pdks.
diff --git a/common/pdk.tcl b/common/pdk.tcl
new file mode 100644
index 0000000..04f32a6
--- /dev/null
+++ b/common/pdk.tcl
@@ -0,0 +1,274 @@
+#-------------------------------------------------------------------
+# General-purpose routines for the PDK script in all technologies
+#-------------------------------------------------------------------
+#
+#----------------------------------------
+# Number Conversion Functions
+#----------------------------------------
+
+#---------------------
+# Microns to Lambda
+#---------------------
+proc magic::u2l {micron} {
+ set techlambda [magic::tech lambda]
+ set tech1 [lindex $techlambda 1]
+ set tech0 [lindex $techlambda 0]
+ set tscale [expr {$tech1 / $tech0}]
+ set lambdaout [expr {((int([magic::cif scale output] * 10000)) / 10000.0)}]
+ return [expr $micron / ($lambdaout*$tscale) ]
+}
+
+#---------------------
+# Lambda to Microns
+#---------------------
+proc magic::l2u {lambda} {
+ set techlambda [magic::tech lambda]
+ set tech1 [lindex $techlambda 1] ; set tech0 [lindex $techlambda 0]
+ set tscale [expr {$tech1 / $tech0}]
+ set lambdaout [expr {((int([magic::cif scale output] * 10000)) / 10000.0)}]
+ return [expr $lambda * $lambdaout * $tscale ]
+}
+
+#---------------------
+# Internal to Microns
+#---------------------
+proc magic::i2u { value } {
+ return [expr {((int([magic::cif scale output] * 10000)) / 10000.0) * $value}]
+}
+
+#---------------------
+# Microns to Internal
+#---------------------
+proc magic::u2i {value} {
+ return [expr {$value / ((int([magic::cif scale output] * 10000)) / 10000.0)}]
+}
+
+#---------------------
+# Float to Spice
+#---------------------
+proc magic::float2spice {value} {
+ if {$value >= 1.0e+6} {
+ set exponent 1e+6
+ set unit "meg"
+ } elseif {$value >= 1.0e+3} {
+ set exponent 1e+3
+ set unit "k"
+ } elseif { $value >= 1} {
+ set exponent 1
+ set unit ""
+ } elseif {$value >= 1.0e-3} {
+ set exponent 1e-3
+ set unit "m"
+ } elseif {$value >= 1.0e-6} {
+ set exponent 1e-6
+ set unit "u"
+ } elseif {$value >= 1.0e-9} {
+ set exponent 1e-9
+ set unit "n"
+ } elseif {$value >= 1.0e-12} {
+ set exponent 1e-12
+ set unit "p"
+ } elseif {$value >= 1.0e-15} {
+ set exponent 1e-15
+ set unit "f"
+ } else {
+ set exponent 1e-18
+ set unit "a"
+ }
+ set val [expr $value / $exponent]
+ set val [expr int($val * 1000) / 1000.0]
+ if {$val == 0} {set unit ""}
+ return $val$unit
+}
+
+#---------------------
+# Spice to Float
+#---------------------
+proc magic::spice2float {value {faultval 0.0}} {
+ # Remove trailing units, at least for some common combinations
+ set value [string tolower $value]
+ set value [string map {um u nm n uF n nF n pF p aF a} $value]
+ set value [string map {meg "* 1.0e6" k "* 1.0e3" m "* 1.0e-3" u "* 1.0e-6" \
+ n "* 1.0 e-9" p "* 1.0e-12" f "* 1.0e-15" a "* 1.0e-15"} $value]
+ if {[catch {set rval [expr $value]}]} {
+ puts stderr "Value is not numeric!"
+ set rval $faultval
+ }
+ return $rval
+}
+
+#---------------------
+# Numeric Precision
+#---------------------
+proc magic::3digitpastdecimal {value} {
+ set new [expr int([expr $value * 1000 + 0.5 ]) / 1000.0]
+ return $new
+}
+
+#-------------------------------------------------------------------
+# File Access Functions
+#-------------------------------------------------------------------
+
+#-------------------------------------------------------------------
+# Ensures that a cell name does not already exist, either in
+# memory or on disk. Modifies the name until it does.
+#-------------------------------------------------------------------
+proc magic:cellnameunique {cellname} {
+ set i 0
+ set newname $cellname
+ while {[cellname list exists $newname] != 0 || [magic::searchcellondisk $newname] != 0} {
+ incr i
+ set newname ${cellname}_$i
+ }
+ return $newname
+}
+
+#-------------------------------------------------------------------
+# Looks to see if a cell exists on disk
+#-------------------------------------------------------------------
+proc magic::searchcellondisk {name} {
+ set rlist {}
+ foreach dir [path search] {
+ set ftry [file join $dir ${name}.mag]
+ if [file exists $ftry] {
+ return 1
+ }
+ }
+ return 0
+}
+
+#-------------------------------------------------------------------
+# Checks to see if a cell already exists on disk or in memory
+#-------------------------------------------------------------------
+proc magic::iscellnameunique {cellname} {
+ if {[cellname list exists $cellname] == 0 && [magic::searchcellondisk $cellname] == 0} {
+ return 1
+ } else {
+ return 0
+ }
+}
+
+#--------------------------------------------------------------
+# Procedure that checks the user's "ip" subdirectory on startup
+# and adds each one's maglef subdirectory to the path.
+#--------------------------------------------------------------
+
+proc magic::query_mylib_ip {} {
+ global TECHPATH
+ global env
+ if [catch {set home $env(SUDO_USER)}] {
+ set home $env(USER)
+ }
+ set homedir /home/${home}
+ set ip_dirs [glob -directory ${homedir}/design/ip *]
+ set proj_dir [pwd]
+ set config_dir .config
+ set info_dir ${proj_dir}/${config_dir}
+ if {![file exists ${info_dir}]} {
+ set config_dir .ef-config
+ set info_dir ${proj_dir}/${config_dir}
+ }
+
+ set info_file ${info_dir}/info
+ set depends [dict create]
+ if {![catch {open $info_file r} ifd]} {
+ set depsec false
+ while {[gets $ifd line] >= 0} {
+ if {[string first dependencies: $line] >= 0} {
+ set depsec true
+ }
+ if {$depsec} {
+ if {[string first version: $line] >= 0} {
+ if {$ipname != ""} {
+ set ipvers [string trim [lindex [split $line] 1] ']
+ dict set depends $ipname $ipvers
+ set ipname ""
+ } else {
+ puts stderr "Badly formatted info file in ${config_dir}!"
+ }
+ } else {
+ set ipname [string trim $line :]
+ }
+ }
+ }
+ }
+
+ foreach dir $ip_dirs {
+ # Version handling: version dependencies are found in
+ # ${config_dir}/info. For all other IP, use the most recent
+ # version number.
+ set ipname [lindex [file split $dir] end]
+ if {![catch {set version [dict get $depends $ipname]}]} {
+ if {[file isdirectory ${dir}/${version}/maglef]} {
+ addpath ${dir}/${version}/maglef
+ continue
+ } else {
+ puts stderr "ERROR: Dependency ${ipname} version ${version} does not exist"
+ }
+ }
+
+ # Secondary directory is the version number. Use the highest
+ # version available.
+
+ set sub_dirs {}
+ catch {set sub_dirs [glob -directory $dir *]}
+ set maxver 0.0
+ foreach subdir $sub_dirs {
+ set vidx [string last / $subdir]
+ incr vidx
+ set version [string range $subdir $vidx end]
+ if {$version > $maxver} {
+ set maxver $version
+ }
+ }
+ if {[file exists ${dir}/${maxver}/maglef]} {
+ # Compatibility rule: foundry name must match.
+ # Get foundry name from ${config_dir}/techdir symbolic link reference
+ if {[file exists ${dir}/${maxver}/${config_dir}/techdir]} {
+ set technodedir [file link ${dir}/${maxver}/${config_dir}/techdir]
+ set nidx [string last / $technodedir]
+ set techdir [string range $technodedir 0 $nidx-1]
+ if {$techdir == $TECHPATH} {
+ addpath ${dir}/${maxver}/maglef
+ }
+ }
+ }
+ }
+}
+
+#--------------------------------------------------------------
+# Procedure that checks the user's design directory on startup
+# and adds each one's mag subdirectory to the path.
+#--------------------------------------------------------------
+
+proc magic::query_my_projects {} {
+ global TECHPATH
+ global env
+ if [catch {set home $env(SUDO_USER)}] {
+ set home $env(USER)
+ }
+ set homedir /home/${home}
+ set proj_dirs [glob -directory ${homedir}/design *]
+ foreach dir $proj_dirs {
+ # Compatibility rule: foundry name must match.
+ # Get foundry name from ${config_dir}/techdir symbolic link reference
+ if {[file exists ${dir}/mag]} {
+ set config_dir .config
+ set tech_dir ${dir}/${config_dir}
+ if {![file exists ${tech_dir}]} {
+ set config_dir .ef-config
+ set tech_dir ${dir}/${config_dir}
+ }
+ if {[file exists ${dir}/${config_dir}/techdir]} {
+ set technodedir [file link ${dir}/${config_dir}/techdir]
+ set nidx [string last / $technodedir]
+ set techdir [string range $technodedir 0 $nidx-1]
+ if {$techdir == $TECHPATH} {
+ addpath ${dir}/mag
+ }
+ }
+ }
+ }
+}
+
+#----------------------------------------------------------------