One more check on valid display which is known to be in the startup
[xcircuit.git] / lib / tcl / sue_xc.tcl
blob072efd6e0c0437ace68cab41d4d8efe1d5c8bfe6
1 #------------------------------------------
2 # sue_xc.tcl
3 #------------------------------------------
4 # This script should be sourced into
5 # XCircuit and provides the capability to
6 # translate .sue files into XCircuit
7 # schematics. This script works properly
8 # with XCircuit version 3.10.21 or newer.
9 #------------------------------------------
10 # The primary routine is "make_all_sue",
11 # which is a TCL procedure to be run from
12 # the XCircuit command line in the directory
13 # containing .sue format files. Without
14 # options, it creates a single XCircuit
15 # PostScript output file "sue_gates.ps",
16 # containing all of the gate symbols and
17 # associated schematics in a single file.
18 #------------------------------------------
19 # Written by R. Timothy Edwards
20 # 8/23/04
21 # MultiGiG, Inc.
22 # Scotts Valley, CA
23 # Updated 4/17/2020: Stopped hard-coding the primitive
24 # devices in favor of making a "sue.lps" library.
25 #------------------------------------------------------------
27 global xscale
28 global sscale
29 # sue puts things on grids of 10, xcircuit on grids of 16.
30 set xscale 16
31 set sscale 10
33 #------------------------------------------------------------
34 # scale an {x y} list value from SUE units to XCircuit units
35 #------------------------------------------------------------
37 proc scale_coord {coord} {
38 global xscale
39 global sscale
40 set x [lindex $coord 0]
41 set y [lindex $coord 1]
42 set x2 [expr {int(($x * $xscale) / $sscale)}]
43 set y2 [expr {int((-$y * $xscale) / $sscale)}]
44 set newc [lreplace $coord 0 1 $x2 $y2]
45 return $newc
48 namespace eval sue {
49 namespace export make make_wire make_line make_text
51 #------------------------------------------------------------
52 # make and make_wire: create the schematic elements
53 #------------------------------------------------------------
55 proc make {type args} {
57 if {[llength $args] == 1} {
58 set args [lindex $args 0]
61 # Default values
62 # Note that the inverted Y axis reverses the meaning of Y in the
63 # orientations.
65 set flipped {}
66 set angle 0
67 set width 1
68 set length 1
69 set name bad_element
70 set origin {0 0}
71 set instance_params {}
73 foreach {key value} $args {
74 switch -- $key {
75 -orient {
76 switch -- $value {
77 RXY {
78 set angle 180
80 RX {
81 set flipped horizontal
83 RY {
84 set flipped vertical
85 set angle 180
87 R270 {
88 set angle 270
90 R90 {
91 set angle 90
93 R0 {
94 # defaults
95 set flipped {}
96 set angle 0
100 -origin {
101 set origin $value
103 -name {
104 set name $value
106 -text {
107 set name $value
109 default {
110 lappend instance_params [list [string range $key 1 end] $value]
115 set origin [scale_coord $origin]
117 switch -- $type {
118 input -
119 output -
120 inout -
121 name_net -
122 name_net_s {
123 set newtext [label make pin $name $origin]
124 rotate $newtext $angle $origin
125 if {$flipped != {}} {
126 flip $newtext $flipped $origin
130 global {
131 set newtext [label make global $name $origin]
132 rotate $newtext $angle $origin
133 if {$flipped != {}} {
134 flip $newtext $flipped $origin
138 text {
139 set newtext [list $name]
140 while {[set rp [string first \n $newtext]] >= 0} {
141 set newtext [string replace $newtext $rp $rp "\} \{return\} \{"]
142 set rp [string first \n $newtext]
144 set newtext [label make normal $newtext $origin]
145 rotate $newtext $angle $origin
146 if {$flipped != {}} {
147 flip $newtext $flipped $origin
151 # Default behavior is to generate an object instance of the
152 # given name. This assumes that these are only objects that
153 # have been defined in .sue files already.
155 default {
156 set newgate [instance make $type $origin]
157 select $newgate
158 rotate $angle $origin
159 if {$flipped != {}} {
160 select $newgate
161 flip $flipped $origin
163 if {$instance_params != {}} {
164 select $newgate
165 foreach pair $instance_params {
166 set key [lindex $pair 0]
167 set value [lindex $pair 1]
168 parameter set $key $value -forward
170 deselect selected
174 deselect selected
177 #------------------------------------------------------------
178 # Draw text on the schematic
179 #------------------------------------------------------------
181 proc make_text {args} {
182 make text $args
185 #------------------------------------------------------------
186 # Draw a wire into the schematic
187 #------------------------------------------------------------
189 proc make_wire {x1 y1 x2 y2} {
190 # Scale the origin from SUE units to XCircuit units
191 set s1 [scale_coord [list $x1 $y1]]
192 set s2 [scale_coord [list $x2 $y2]]
193 polygon make 2 $s1 $s2
196 proc make_line {args} {
197 eval "make_wire $args"
201 #------------------------------------------------------------
202 # icon_*: create the symbol
203 #------------------------------------------------------------
205 #------------------------------------------------------------
206 # default parameters (deferred)
207 #------------------------------------------------------------
209 proc icon_setup {icon_args params} {
210 puts stdout "icon_setup $icon_args $params"
212 foreach pair $params {
213 set key [lindex $pair 0]
214 set value [lindex $pair 1]
215 if {$value == {}} {set value ""}
216 switch -- $key {
217 origin -
218 orient {
219 # Do nothing for now. These are library instance values
220 # in xcircuit, and could be set as such.
222 default {
223 parameter make substring $key [list [list Text $value]]
229 #------------------------------------------------------------
230 # pins
231 #------------------------------------------------------------
233 proc icon_term {args} {
234 puts stdout "icon_term $args"
235 set pintype "no_pin"
236 set origin {0 0}
237 set name "bad_pin_name"
239 foreach {key value} $args {
240 switch -- $key {
241 -type {
242 set pintype $value
244 -origin {
245 set origin $value
247 -name {
248 set name $value
252 set newtext [label make pin $name [scale_coord $origin]]
253 label $newtext anchor center
254 label $newtext anchor middle
255 deselect selected
258 #------------------------------------------------------------
259 # instance parameters and symbol text labels
260 #------------------------------------------------------------
262 proc icon_property {args} {
264 puts stdout "icon_property $args"
266 set name {}
267 set origin {0 0}
268 set proptype {}
269 set lscale 0.7
271 foreach {key value} $args {
273 switch -- $key {
274 -origin {
275 set origin $value
277 -name {
278 set lhandle [label make normal [list [list Parameter $value]] [scale_coord $origin]]
279 label $lhandle anchor center
280 label $lhandle anchor middle
281 label $lhandle scale $lscale
282 deselect selected
284 -type {
285 set proptype $value
287 -size {
288 # label size. Ignore, for now.
289 switch -- $value {
290 -small {
291 set lscale 0.5
293 -large {
294 set lscale 0.9
296 default {
297 set lscale 0.7
301 -label {
302 set lhandle [label make normal "$value" [scale_coord $origin]]
303 label $lhandle anchor center
304 label $lhandle anchor middle
305 label $lhandle scale $lscale
306 deselect selected
312 #------------------------------------------------------------
313 # Line drawing on the symbol
314 #------------------------------------------------------------
316 proc icon_line {args} {
317 puts stdout "icon_line $args"
318 set coords {}
319 set i 0
320 foreach {x y} $args {
321 set s [scale_coord [list $x $y]]
322 lappend coords $s
323 incr i
325 eval "polygon make $i $coords"
328 #------------------------------------------------------------
329 # Recast schematic commands in a namespace used for a
330 # preliminary parsing to discover dependencies
331 #------------------------------------------------------------
333 namespace eval parse {
334 namespace export make make_wire make_line make_text
336 proc make {type args} {
337 global deplist
339 switch -- $type {
340 input -
341 output -
342 inout -
343 name_net -
344 name_net_s -
345 global -
346 text {
348 default {
349 lappend deplist $type
354 proc make_line {args} {
357 proc make_wire {x1 y1 x2 y2} {
360 proc make_text {args} {
364 #------------------------------------------------------------
365 # Main routine: Load the .sue file for the indicated
366 # gate. Draw the schematic and the (user library) symbol,
367 # and associate them.
368 #------------------------------------------------------------
370 proc make_sue_gate {filename libname} {
371 global deplist
373 set name [file tail [file root $filename]]
375 # Check if this gate exists and ignore if so (may have been
376 # handled already as a dependency to another gate)
377 if {![catch {object handle ${name}}]} {return}
379 # DIAGNOSTIC
380 puts stdout "Sourcing ${filename}"
381 source ${filename}
383 set deplist {}
385 # DIAGNOSTIC
386 puts stdout "Evaluating SCHEMATIC_${name} in namespace parse"
387 namespace import parse::*
388 eval "SCHEMATIC_${name}"
390 if {[llength $deplist] > 0} {
391 # DIAGNOSTIC
392 puts stdout "Handling dependency list."
393 foreach dep $deplist {
394 make_sue_gate ${dep}.sue $libname
398 # DIAGNOSTIC
399 puts stdout "Generating new page"
401 # Go to a new page unless the current one is empty
402 while {[llength [object parts]] > 0} {
403 set p [page]
404 incr p
405 while {[catch {page $p}]} {
406 page make
410 puts stdout "Evaluating ICON_${name}"
411 namespace forget parse::*
412 namespace import sue::*
414 # Evaluate the symbol. Generate the symbol in xcircuit.
415 # Then clear the page to make the schematic
416 eval "ICON_${name}"
417 set hlist [object parts]
418 object make $name $hlist
419 set hlist [object parts]
420 push $hlist
422 delete $hlist
424 # DIAGNOSTIC
425 puts stdout "Evaluating SCHEMATIC_${name} in namespace sue"
427 eval "SCHEMATIC_${name}"
428 catch {wm withdraw .select}
429 schematic associate $name
430 zoom view
432 # DIAGNOSTIC
433 puts stdout "Done."
434 namespace forget sue::*
437 #------------------------------------------------------------
438 # Read a .sue file and source it, then format a page around
439 # the schematic contents.
440 #------------------------------------------------------------
442 proc read_sue_file {filename name} {
443 config suspend true
444 make_sue_gate $filename $name
445 page filename $name
446 page orientation 90
447 page encapsulation full
448 page fit true
449 if {[page scale] > 1.0} {
450 page fit false
451 page scale 1.0
453 config suspend false
456 #------------------------------------------------------------
457 # Top-level routine: Find all the .sue files in the
458 # current directory and generate a library from them
459 #------------------------------------------------------------
461 proc make_all_sue {{name sue_gates}} {
462 set files [glob \*.sue]
464 foreach filename $files {
465 read_sue_file $filename $name
469 #------------------------------------------------------------
470 # Make sure that the sue technology (.lps file) has been read
472 #------------------------------------------------------------
474 if {[lsearch [technology list] sue] < 0} {
475 library load sue
476 technology prefer sue