1# Wishrc startup for ToolScript (magic)
2#
3# For installation:  Put this file and also magicwrap.so into
4# the same directory. Also see comments in shell script "magic.sh".
5
6global Opts
7
8# If we called magic via the non-console script, then we want to reset
9# the environment variable HOME to its original value.
10
11variable MAGIC_TCL_DIR [file dirname [file normalize [info script]]]
12variable CAD_ROOT_DEFAULT [file normalize [file join $MAGIC_TCL_DIR ../..]]
13
14if {${tcl_version} >= 8.6} {
15   load -lazy [file join $MAGIC_TCL_DIR tclmagic[info sharedlibextension]]
16} else {
17   load [file join $MAGIC_TCL_DIR tclmagic[info sharedlibextension]]
18}
19
20# It is important to make sure no magic commands overlap with Tcl built-in
21# commands, because otherwise the namespace import will fail.
22
23proc pushnamespace { name } {
24
25   set y [namespace eval ${name} info commands ::${name}::*]
26   set z [info commands]
27
28# Watch especially for magic "wizard" commands, as we don't want to confuse
29# the literal "*" with a regular expression *.  "regsub" below takes care of it.
30
31   foreach v $y {
32      regsub -all {\*} $v {\\*} i
33      set x [namespace tail $i]
34      if {[lsearch $z $x] < 0} {
35         namespace import $i
36      }
37   }
38}
39
40proc popnamespace { name } {
41   set z [info commands]
42   set l [expr [string length ${name}] + 5]
43
44   while {[set v [lsearch $z ${name}_tcl_*]] >= 0} {
45      set y [lindex $z $v]
46      set w [string range $y $l end]
47      interp alias {} ::$w {}
48      rename ::$y ::$w
49      puts "Info: replacing ::$w with ::$y"
50   }
51   namespace forget ::${name}::*
52}
53
54#----------------------------------------------------------------------
55# Define the drcstate procedure expected by the background DRC code.
56
57proc magic::drcstate {option} {
58   # (Null proc---see wrapper.tcl for a useful version)
59}
60
61#-----------------------------------------------------------------
62# Define these console routines so that they don't produce errors
63# when Magic is run in batch mode
64
65if {[catch {tkcon title}]} {
66   proc magic::suspendout {} {}
67   proc magic::resumeout {} {}
68   proc magic::dialog {} {}
69   proc magic::consolegeometry {} {}
70   proc magic::consolefocus {} {}
71}
72
73#----------------------------------------------------------------------
74# Cross-Application section
75#----------------------------------------------------------------------
76
77# Check namespaces for existence of other applications
78set UsingIRSIM 0
79set UsingXCircuit 0
80set UsingNetgen 0
81set nlist [namespace children]
82foreach i $nlist {
83   switch $i {
84      ::irsim { set UsingIRSIM 1 }
85      ::xcircuit { set UsingXCircuit 1 }
86      ::netgen { set UsingNetgen 1 }
87   }
88}
89
90# Setup IRSIM assuming that the Tcl version is installed.
91# We do not need to rename procedure irsim to NULL because it is
92# redefined in a script, which simply overwrites the original.
93
94proc irsim { args } {
95   global CAD_ROOT
96   set irsimscript [glob -nocomplain ${CAD_ROOT}/irsim/tcl/irsim.tcl]
97   if { ${irsimscript} == {} } {
98      puts stderr "\"irsim\" requires Tcl-based IRSIM version 9.6 or newer."
99      puts stderr "Could not find script \"irsim.tcl\".  If IRSIM is installed in a"
100      puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
101      puts stderr "\"source <path>/irsim.tcl\" before doing \"irsim\"."
102   } else {
103      source $irsimscript
104      eval {irsim} $args
105   }
106}
107
108# Setup Xcircuit assuming that the Tcl version is installed.
109
110proc xcircuit { args } {
111   global CAD_ROOT
112   global argc
113   global argv
114   set xcircscript [glob -nocomplain ${CAD_ROOT}/xcircuit*/xcircuit.tcl]
115   if { ${xcircscript} == {} } {
116      puts stderr "\"xcircuit\" requires Tcl-based XCircuit version 3.1 or newer."
117      puts stderr "Could not find script \"xcircuit.tcl\".  If XCircuit is installed in a"
118      puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
119      puts stderr "\"source <path>/xcircuit.tcl\"."
120   } else {
121      # if there are multiple installed versions, choose the highest version.
122      if {[llength $xcircscript] > 1} {
123	set xcircscript [lindex [lsort -decreasing -dictionary $xcircscript] 0]
124      }
125      # execute script in the scope of magic, because its variable space is
126      # not modularized.
127      set argv $args
128      set argc [llength $args]
129      uplevel #0 source $xcircscript
130   }
131}
132
133# Setup Netgen assuming that the Tcl version is installed.
134
135proc netgen { args } {
136   global CAD_ROOT
137   global argc
138   global argv
139   set netgenscript [glob -nocomplain ${CAD_ROOT}/netgen/tcl/netgen.tcl]
140   if { ${netgenscript} == {} } {
141      puts stderr "\"netgen\" requires Tcl-based Netgen version 1.2 or newer."
142      puts stderr "Could not find script \"netgen.tcl\".  If Netgen is installed in a"
143      puts stderr "place other than CAD_ROOT (=${CAD_ROOT}), use the command"
144      puts stderr "\"source <path>/netgen.tcl\"."
145   } else {
146      set argv $args
147      set argc [llength $args]
148      uplevel #0 source $netgenscript
149   }
150}
151
152# Add the "echo" command
153
154proc echo {args} {
155   puts stdout $args
156}
157
158# Parse argument list for "-c[onsole]" and "-now[rapper]".
159
160set celllist {}
161set do_wrapper true
162set do_recover false
163set argafter {magic::initialize}
164set x {}
165for {set i 0} {$i < $argc} {incr i 1} {
166   set x [lindex $argv $i]
167#
168# Command-line argument handling goes here
169# We have to handle all of magic's command line arguments so we can
170# figure out if a cell has been named for preloading.
171#
172   switch -regexp -- $x {
173      ^-now(rap)?(per)?$ {	  ;# This regexp accepts -now, -nowrap, and -nowrapper
174	 set do_wrapper false
175      }
176      ^-dnull {
177	 set do_wrapper false
178         lappend argafter $x
179      }
180      ^-r(e)?(cover)?$ {
181	 set do_recover true
182      }
183      ^-rc(file)?$ {
184         lappend argafter $x
185         incr i 1
186         lappend argafter [lindex $argv $i]
187      }
188      ^-d -
189      ^-g -
190      ^-m -
191      ^-i -
192      ^-T {
193         lappend argafter $x
194         incr i 1
195         lappend argafter [lindex $argv $i]
196      }
197      ^-F {
198         lappend argafter $x
199         incr i 1
200         lappend argafter [lindex $argv $i]
201         incr i 1
202         lappend argafter [lindex $argv $i]
203      }
204      ^--version {
205	 puts stdout "MAGIC_VERSION.MAGIC_REVISION"
206	 exit 0
207      }
208      ^--prefix {
209	 puts stdout $CAD_ROOT
210	 exit 0
211      }
212      ^-D -
213      ^-n* {
214         lappend argafter $x
215      }
216      default {
217         lappend celllist $x
218         lappend argafter $x
219      }
220   }
221}
222
223if {$do_wrapper} {
224  source ${CAD_ROOT}/magic/tcl/wrapper.tcl
225  lappend argafter "-nowindow" ;# Set no-initial-window option in magic.
226}
227unset x i do_wrapper
228if {[catch {eval $argafter}]}  {		;# magic::initialize ${argv}
229   exit 1
230}
231
232#----------------------------------------------------------------------
233# Check for presence of padlist manager script and include it
234
235if {[file exists ${CAD_ROOT}/magic/tcl/padlist.tcl]} {
236   source ${CAD_ROOT}/magic/tcl/padlist.tcl
237   set Opts(padlist) 0
238}
239
240#----------------------------------------------------------------------
241# Check for presence of the miscellaneous tools script and include it
242
243if {[file exists ${CAD_ROOT}/magic/tcl/tools.tcl]} {
244   source ${CAD_ROOT}/magic/tcl/tools.tcl
245   set Opts(tools) 0
246}
247
248#----------------------------------------------------------------------
249# Check for presence of the mazerouter script and include it
250
251if {[file exists ${CAD_ROOT}/magic/tcl/mazeroute.tcl]} {
252   source ${CAD_ROOT}/magic/tcl/mazeroute.tcl
253   set Opts(mazeroute) 0
254}
255
256#----------------------------------------------------------------------
257# Check for presence of the toolkit script and include it
258# NOTE:  This supercedes the older toolkit which is now
259# named toolkit_rev0.tcl, and the intermediate bsitools.tcl,
260# which are folded into the newer toolkit.tcl.
261
262if {[file exists ${CAD_ROOT}/magic/tcl/toolkit.tcl]} {
263   source ${CAD_ROOT}/magic/tcl/toolkit.tcl
264   set Opts(toolkit) 0
265}
266
267#----------------------------------------------------------------------
268# Check for presence of the readspice script and include it
269
270if {[file exists ${CAD_ROOT}/magic/tcl/readspice.tcl]} {
271   source ${CAD_ROOT}/magic/tcl/readspice.tcl
272   set Opts(readspice) 0
273}
274
275#----------------------------------------------------------------------
276# Magic start function drops back to interpreter after initialization & setup
277
278set auto_noexec 1	;# don't EVER call UNIX commands w/o "shell" in front
279
280# Have we called magic from tkcon or a clone thereof?  If so, set MagicConsole
281
282if {[lsearch [interp aliases] tkcon] != -1} {
283   set MagicConsole tkcon
284   catch {wm withdraw .}
285
286   # Get rid of some overlapping tkcon commands which are not needed.
287
288   if {[lsearch [info commands] orig_edit] < 0} {rename edit orig_edit}
289   if {[lsearch [info commands] orig_dump] < 0} {rename dump orig_dump}
290   if {[lsearch [info commands] orig_what] < 0} {rename what orig_what}
291} else {
292   rename unknown tcl_unknown
293   proc unknown { args } {
294      # CAD tools special:
295      # Check for commands which were renamed to tcl_(command)
296
297      set cmd [lindex $args 0]
298      if {[lsearch [info commands] tcl_$cmd] >= 0} {
299         set arglist [concat tcl_$cmd [lrange $args 1 end]]
300         set ret [catch {eval $arglist} result]
301         if {$ret == 0} {
302            return $result
303         } else {
304            return -code $ret -errorcode $errorCode $result
305         }
306      }
307      return [eval [concat tcl_unknown $args]]
308   }
309}
310
311# Set up certain commands to act like they do in non-Tcl-based magic;
312# These are the commands whose names have been extended so they don't
313# conflict with existing Tcl/Tk commands.  This renaming & importing
314# *requires* the special code in the magic Tcl command dispatcher to
315# find and deal with each of these renamed commands!
316
317if {[lsearch [info commands] orig_clock] < 0} {rename clock orig_clock}
318if {[lsearch [info commands] tcl_flush] < 0} {rename flush tcl_flush}
319if {[lsearch [info commands] tcl_load] < 0} {rename load  tcl_load}
320if {[lsearch [info commands] tcl_array] < 0} {rename array tcl_array}
321if {[lsearch [info commands] tcl_label] < 0} {catch {rename label tcl_label}}
322if {[lsearch [info commands] tcl_grid] < 0} {catch {rename grid tcl_grid}}
323
324namespace eval magic namespace export *
325pushnamespace magic
326
327#----------------------------------------------------------------------
328# Read system startup files (mostly macro definitions)
329# Read user startup file, if any
330# Load initial cell, if any
331
332magic::startup
333
334if {![catch {set toptitle [wm title .]}]} {
335   if {[string range $toptitle 0 3] == "wish"} {
336      wm withdraw .
337   }
338   if {[string range $toptitle 0 8] == "magicexec"} {
339      wm withdraw .
340   }
341   unset toptitle
342}
343
344# After loading, magic will wander off and do a complete DRC check
345# before executing the rest of the script unless we temporarily
346# disable the DRC checker.
347
348set drcstate [drc status]
349drc off
350
351# Initial window for wrapper, if defined.
352# empty string is equivalent to passing NULL cell name.
353#
354# If a startup file has created a window, then don't make another one.
355
356if {[info commands magic::openwrapper] != {}} {
357   if {[windownames layout] == {}} {
358      set winname [magic::openwrapper]
359      magic::techmanager initall
360      magic::scrollupdate $winname
361
362      foreach cellname $celllist {
363	 set fext [file extension $cellname]
364         puts stdout "handling file entry $cellname extension $fext"
365	 switch $fext {
366	     .lef -
367	     .LEF {lef read $cellname}
368	     .def -
369	     .DEF {def read $cellname}
370	     .gds -
371	     .GDS -
372	     .gds2 -
373	     .GDS2 -
374	     .gdsii -
375	     .GDSII {gds read $cellname}
376	     .cif -
377	     .CIF {cif read $cellname}
378	     .tcl {source $cellname}
379	     .mag -
380	     "" {magic::load $cellname}
381	     default {puts stderr "don't know how to load file $cellname"}
382	 }
383      }
384   }
385} else {
386   # Initial geometry handler for the default window, non-wrapper version
387   catch {wm geometry .magic1 ${Opts(geometry)}}
388}
389
390# Print the technology name and description
391puts stdout "Using technology \"[tech name]\", version [lindex [tech version] 0]"
392
393# Set a box, and set the view; if no cell has been loaded, choose a default
394# view.
395if {![box exists]} {
396   box 0 0 1 1		;# create a unit box
397}
398if {[llength $celllist] > 0} {
399   view
400} else {
401   view -9 -9 10 10
402}
403
404# The Tcl version handles the "-r" on the command line by calling
405# command crash recover.
406
407if {$do_recover} {crash recover}
408
409# Unset global TCL variables so they don't conflict with magic nodes.
410unset celllist nlist do_recover
411
412if {$drcstate == 1} {
413   drc on
414}
415unset drcstate
416