1 #------------------------------------------
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
23 # Updated 4/17/2020: Stopped hard-coding the primitive
24 # devices in favor of making a "sue.lps" library.
25 #------------------------------------------------------------
29 # sue puts things on grids of 10, xcircuit on grids of 16.
33 #------------------------------------------------------------
34 # scale an {x y} list value from SUE units to XCircuit units
35 #------------------------------------------------------------
37 proc scale_coord
{coord
} {
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]
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]
62 # Note that the inverted Y axis reverses the meaning of Y in the
71 set instance_params
{}
73 foreach {key value
} $args {
81 set flipped horizontal
110 lappend instance_params
[list [string range
$key 1 end
] $value]
115 set origin
[scale_coord
$origin]
123 set newtext
[label make pin
$name $origin]
124 rotate
$newtext $angle $origin
125 if {$flipped != {}} {
126 flip
$newtext $flipped $origin
131 set newtext
[label make
global $name $origin]
132 rotate
$newtext $angle $origin
133 if {$flipped != {}} {
134 flip
$newtext $flipped $origin
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.
156 set newgate
[instance make
$type $origin]
158 rotate
$angle $origin
159 if {$flipped != {}} {
161 flip
$flipped $origin
163 if {$instance_params != {}} {
165 foreach pair
$instance_params {
166 set key
[lindex $pair 0]
167 set value
[lindex $pair 1]
168 parameter
set $key $value -forward
177 #------------------------------------------------------------
178 # Draw text on the schematic
179 #------------------------------------------------------------
181 proc 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
""}
219 # Do nothing for now. These are library instance values
220 # in xcircuit, and could be set as such.
223 parameter make substring
$key [list [list Text
$value]]
229 #------------------------------------------------------------
231 #------------------------------------------------------------
233 proc icon_term
{args
} {
234 puts stdout
"icon_term $args"
237 set name
"bad_pin_name"
239 foreach {key value
} $args {
252 set newtext
[label make pin
$name [scale_coord
$origin]]
253 label $newtext anchor center
254 label $newtext anchor middle
258 #------------------------------------------------------------
259 # instance parameters and symbol text labels
260 #------------------------------------------------------------
262 proc icon_property
{args
} {
264 puts stdout
"icon_property $args"
271 foreach {key value
} $args {
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
288 # label size. Ignore, for now.
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
312 #------------------------------------------------------------
313 # Line drawing on the symbol
314 #------------------------------------------------------------
316 proc icon_line
{args
} {
317 puts stdout
"icon_line $args"
320 foreach {x y
} $args {
321 set s
[scale_coord
[list $x $y]]
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
} {
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
} {
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}
380 puts stdout
"Sourcing ${filename}"
386 puts stdout
"Evaluating SCHEMATIC_${name} in namespace parse"
387 namespace import parse
::*
388 eval "SCHEMATIC_${name}"
390 if {[llength $deplist] > 0} {
392 puts stdout
"Handling dependency list."
393 foreach dep
$deplist {
394 make_sue_gate
${dep
}.sue
$libname
399 puts stdout
"Generating new page"
401 # Go to a new page unless the current one is empty
402 while {[llength [object parts
]] > 0} {
405 while {[catch {page
$p}]} {
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
417 set hlist
[object parts
]
418 object make
$name $hlist
419 set hlist
[object parts
]
425 puts stdout
"Evaluating SCHEMATIC_${name} in namespace sue"
427 eval "SCHEMATIC_${name}"
428 catch {wm withdraw .select
}
429 schematic associate
$name
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
} {
444 make_sue_gate
$filename $name
447 page encapsulation full
449 if {[page
scale] > 1.0} {
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} {
476 technology prefer sue